java Spring batch test step scoped bean with @BeforeStep always NPE

zujrkrfu  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(123)

这是我想测试的步骤范围的项目读取器,在读取字符串列表之前应该在@BeforeStep中初始化

@Slf4j
@Component
@StepScope
@RequiredArgsConstructor
public class SomeItemReader implements ItemReader<String> {

    @Value("#{jobParameters['date']}")
    private String date;
    private List<String> stringList;

    private final SomeService someService; //its inteface

    @BeforeStep
    public void init() {
            stringList = new LinkedList<>(someService.getList(LocalDate.parse(date)));
    }

    @Override
    public String read() {
        return !stringList.isEmpty() ? stringList.remove(0) : null;
    }

并测试

@ContextConfiguration
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        StepScopeTestExecutionListener.class})
@RunWith(SpringRunner.class)
class SomeItemReaderTest {

    @Autowired
    private SomeItemReader someItemReader;

 public StepExecution getStepExecution() {
        StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        execution.getExecutionContext().putString("input.data", "foo,bar,spam");
        return execution;
    }

@Test
void read() {
    assertNotNull(someItemReader.read());//always get NPE here
}

}
我错过了什么或它不可能测试它?

mznpcxlj

mznpcxlj1#

@BeforeStep注解的方法在执行步骤(涉及读取器)之前执行。在测试中,没有步骤运行,因此您不应该期望调用此方法。
此外,您在date字段中注入了一个作业参数,但测试并没有准备任何作业参数,而是在步骤执行上下文中添加了键/值par ["input.data"="foo,bar,spam"],读取器不使用它。
因此,要回答您关于如何测试配置了job参数的step-scoped bean的问题,您需要:
1.创建使用作业参数准备的步骤执行
1.将reader声明为Springbean,以便根据需要进行代理
1.在测试类中自动连接读取器,并使用StepScopeTestUtils.doInStepScope模拟步骤范围内的执行
下面是一个完整的示例(基于Spring Batch 5和JUnit 5):

package org.springframework.batch.test;

import java.util.List;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.support.IteratorItemReader;
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.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
public class SO75911081 {

    @Autowired
    private MyItemReader itemReader;

    @Test
    void testStepScopedReader() throws Exception {
        // given
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("prefix", "test-")
                .toJobParameters();
        StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters);

        // when
        String item = StepScopeTestUtils.doInStepScope(stepExecution, this.itemReader::read);

        // then
        Assertions.assertEquals("test-foo", item);
    }

    @Configuration
    static class MyConfiguration {

        @Bean
        @StepScope
        public MyItemReader itemReader() {
            return new MyItemReader(List.of("foo"));
        }

        @Bean // not needed when using EnableBatchProcessing
        org.springframework.batch.core.scope.StepScope scope() {
            return new org.springframework.batch.core.scope.StepScope();
        }

    }
    static class MyItemReader extends IteratorItemReader<String> {

        @Value("#{jobParameters['prefix']}")
        private String prefix;

        public MyItemReader(List<String> list) {
            super(list);
        }

        @Override
        public String read() {
            String item = super.read();
            return item != null ? prefix + item : null;
        }
    }
}

相关问题