【问题标题】:Spring-Batch: Testing custom itemReaderSpring-Batch:测试自定义 itemReader
【发布时间】:2020-02-17 20:12:58
【问题描述】:

我正在尝试测试我的自定义 itemReader:

@Bean
@StepScope
MyMultiLineItemReader itemReader(@Value("#{stepExecutionContext['fileName']}") String filename) throws MalformedURLException {
MyMultiLineItemReader itemReader = new MyMultiLineItemReader();
itemReader.setDelegate(myFlatFileItemReader(filename));

return itemReader;
}

@Bean
@StepScope
public FlatFileItemReader<String> myFlatFileItemReader(@Value("#{stepExecutionContext['fileName']}") String filename) throws MalformedURLException {
return new FlatFileItemReaderBuilder<String>()
.name("myFlatFileItemReader")
.resource(new UrlResource(filename))
.lineMapper(new PassThroughLineMapper())
.build();
}

我的测试类看起来像

@Test
public void givenMockedStep_whenReaderCalled_thenSuccess() throws Exception {
    // given
    JobExecution jobExecution = new JobExecution(5l);
    ExecutionContext ctx = new ExecutionContext();
    ctx.put("fileName", "src/main/resources/data/input.txt");
    jobExecution.setExecutionContext(ctx);

    JobSynchronizationManager.register(jobExecution);
    StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(ctx);

    // when
    StepScopeTestUtils.doInStepScope(stepExecution, () -> {
     ...
     });
}

当我运行测试用例时,过程失败,因为 fileName 参数为空。

我正在寻找测试 itemReader 的正确方法。

谢谢

【问题讨论】:

    标签: java junit spring-batch


    【解决方案1】:

    您无需创建 JobExecution 并将其注册到 JobSynchronizationManager 即可测试步进范围的组件。模拟一个步骤执行并在StepScopeTestUtils.doInStepScope 中使用它就足够了。这是一个完整的例子:

    import java.util.ArrayList;
    import java.util.List;
    
    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.EnableBatchProcessing;
    import org.springframework.batch.core.configuration.annotation.StepScope;
    import org.springframework.batch.item.ExecutionContext;
    import org.springframework.batch.item.file.FlatFileItemReader;
    import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
    import org.springframework.batch.item.file.mapping.PassThroughLineMapper;
    import org.springframework.batch.test.MetaDataInstanceFactory;
    import org.springframework.batch.test.StepScopeTestUtils;
    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.core.io.ClassPathResource;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @ContextConfiguration(classes = StepScopedComponentTest.MyConfiguration.class)
    public class StepScopedComponentTest {
    
        @Autowired
        private FlatFileItemReader<String> reader;
    
        @Test
        public void givenMockedStep_whenReaderCalled_thenSuccess() throws Exception {
            // given
            ExecutionContext ctx = new ExecutionContext();
            ctx.put("fileName", "data/input.txt");
            StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(ctx);
    
            // when
            List<String> items = StepScopeTestUtils.doInStepScope(stepExecution, () -> {
                List<String> result = new ArrayList<>();
                String item;
                reader.open(stepExecution.getExecutionContext());
                while ((item = reader.read()) != null) {
                    result.add(item);
                }
                reader.close();
                return result;
            });
    
            // then
            Assert.assertEquals(2, items.size());
            Assert.assertEquals("foo", items.get(0));
            Assert.assertEquals("bar", items.get(1));
        }
    
        @Configuration
        @EnableBatchProcessing
        static class MyConfiguration {
    
            @Bean
            @StepScope
            public FlatFileItemReader<String> myFlatFileItemReader(@Value("#{stepExecutionContext['fileName']}") String filename) {
                return new FlatFileItemReaderBuilder<String>()
                        .name("myFlatFileItemReader")
                        .resource(new ClassPathResource(filename))
                        .lineMapper(new PassThroughLineMapper())
                        .build();
            }
        }
    
    }
    

    假设类路径资源 data/input.txt 包含行 foo 和 bar,则此测试通过。

    【讨论】:

    • StepScopedComponentTest.MyConfiguration.class 包含什么?我总是得到 No qualifying bean of type 'org.springframework.batch.core.Job' available.
    • @TomasLukac 上面的例子是自包含的。 MyConfiguration 类是StepScopedComponentTest 中的静态内部类,可以在示例中看到。问题是关于测试一个步进范围的阅读器,在这种情况下不需要定义一个工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多