繁体   English   中英

在单元测试执行期间未调用@BeforeStep方法

[英]@BeforeStep method is not called during unit test execution

我有一个ItemProcessor ,它具有@BeforeStep方法来访问ExecutionContext

public class MegaProcessor implements ItemProcessor<String, String> {

    private ExecutionContext context;

    @BeforeStep
    void getExecutionContext(final StepExecution stepExecution) {
        this.context = stepExecution.getExecutionContext();
    }

    @Override
    public String process(final String string) throws Exception {
     // ...
    }
}

此类的单元测试:

@ContextConfiguration(classes = MegaProcessor.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
@RunWith(SpringRunner.class)
public class MegaProcessorTest {

    @Autowired
    private MegaProcessor sut;

    public StepExecution getStepExecution() {
        StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        execution.getExecutionContext().put("data", "yeah");
        return execution;
    }

    @Test
    public void MegaProcessor() throws Exception {
        assertNotNull(sut.process("pew pew"));
    }
}

当我调试测试运行时, contextnull并且永远不会调用@BeforeStep方法。 为什么会这样以及如何实现呢?

这是为什么

如果要使用StepScopeTestExecutionListener ,则应该对测试的组件进行逐步作用域检查(请参阅Javadoc )。 在您的示例中情况并非如此。 但这不是真正的问题。 真正的问题是在执行处理器注册步骤之前,将调用带有@BeforeStep注释的方法。 在您的测试用例中,没有任何步骤在运行,因此永远不会调用该方法。

如何实现?

由于它是一个单元测试,因此您可以假设在运行该步骤并将其模拟/存入单元测试之前,Spring Batch将把步骤执行传递给项目处理器。 这就是我对组件进行单元测试的方式:

import org.junit.Before;
import org.junit.Test;

import org.springframework.batch.core.StepExecution;

import static org.junit.Assert.assertNotNull;

public class MegaProcessorTest {

    private MegaProcessor sut;

    @Before
    public void setUp() {
        StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        execution.getExecutionContext().put("data", "yeah");
        sut = new MegaProcessor();
        sut.getExecutionContext(execution); // I would rename getExecutionContext to setExecutionContext
    }

    @Test
    public void MegaProcessor() throws Exception {
        assertNotNull(sut.process("pew pew"));
    }

}

当您具有使用后绑定从步骤执行上下文中获取值的步骤作用域组件时, StepScopeTestExecutionListener会很方便。 例如:

@Bean
@StepScope
public ItemReader<String> itemReader(@Value("#{stepExecutionContext['items']}") String[] items) {
        return new ListItemReader<>(Arrays.asList(items));
}

该阅读器的单元测试将类似于:

import java.util.Arrays;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;

@ContextConfiguration(classes = StepScopeExecutionListenerSampleTest.MyApplicationContext.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
@RunWith(SpringRunner.class)
public class StepScopeExecutionListenerSampleTest {

    @Autowired
    private ItemReader<String> sut;

    public StepExecution getStepExecution() {
        StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        execution.getExecutionContext().put("items", new String[] {"foo", "bar"});
        return execution;
    }

    @Test
    public void testItemReader() throws Exception {
        Assert.assertEquals("foo", sut.read());
        Assert.assertEquals("bar", sut.read());
        Assert.assertNull(sut.read());
    }

    @Configuration
    static class MyApplicationContext {

        @Bean
        @StepScope
        public ItemReader<String> itemReader(@Value("#{stepExecutionContext['items']}") String[] items) {
            return new ListItemReader<>(Arrays.asList(items));
        }

        /*
         * Either declare the step scope like the following or annotate the class
         * with `@EnableBatchProcessing` and the step scope will be added automatically
         */
        @Bean
        public static org.springframework.batch.core.scope.StepScope stepScope() {
            org.springframework.batch.core.scope.StepScope stepScope = new org.springframework.batch.core.scope.StepScope();
            stepScope.setAutoProxy(false);
            return stepScope;
        }
    }

}

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM