junit Spring批次:正在测试自定义itemReader

pxiryf3j  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(164)

我正在尝试测试我的自定义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参数为null,因此流程失败。
我正在寻找测试itemReader的正确方法。
谢谢

9jyewag0

9jyewag01#

你不需要创建一个JobExecution并在JobSynchronizationManager中注册它来测试一个step-scoped组件。模拟一个step-execution并在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包含两行foobar,则此测试通过。

相关问题