[英]@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"));
}
}
當我調試測試運行時, context
為null
並且永遠不會調用@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.