Java Spring批处理JpaPagingItemReader在测试中没有EntityManager(NPE)
我有一个使用Java Spring批处理JpaPagingItemReader在测试中没有EntityManager(NPE),java,jpa,spring-batch,h2,Java,Jpa,Spring Batch,H2,我有一个使用JpaPagingItemReader的小型Spring批处理作业。当我从命令行启动时,该作业运行良好,但当我想测试@StepScope组件JpaPagingItemReader时,我会得到一个NullPointerException。我不明白为什么工作很好,但我不能测试它根据文件 我只有一个简单的Employee类,带有基本JPA注释 以下是我的作业配置类: @Slf4j @Configuration @EnableBatchProcessing public class PayS
JpaPagingItemReader
的小型Spring批处理作业。当我从命令行启动时,该作业运行良好,但当我想测试@StepScope
组件JpaPagingItemReader
时,我会得到一个NullPointerException
。我不明白为什么工作很好,但我不能测试它根据文件
我只有一个简单的Employee
类,带有基本JPA
注释
以下是我的作业配置类:
@Slf4j
@Configuration
@EnableBatchProcessing
public class PaySalaryJobConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Autowired
public PaySalaryJobConfiguration(
JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory
) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
@Bean
@StepScope
public ItemProcessor<Employee, Employee> employeeProcessor() {
return item -> {
log.info("Process item: {}", item);
return item;
};
}
@Bean
@StepScope
public JpaPagingItemReader<Employee> someoneReader(
EntityManagerFactory entityManagerFactory
) {
return new JpaPagingItemReaderBuilder<Employee>()
.name("someone-reader")
.entityManagerFactory(entityManagerFactory)
.queryString("Select e from Employee e order by e.id asc")
.pageSize(1)
.build();
}
@Bean
@StepScope
public FlatFileItemWriter<Employee> csvWriter(
@Value("#{jobParameters['output.path.csv']}") String outputPath
) {
DelimitedLineAggregator<Employee> lineAggregator = new DelimitedLineAggregator<>();
lineAggregator.setDelimiter(",");
BeanWrapperFieldExtractor<Employee> fieldExtractor = new BeanWrapperFieldExtractor<>();
fieldExtractor.setNames(new String[]{"id", "firstName", "lastName", "salary"});
lineAggregator.setFieldExtractor(fieldExtractor);
return new FlatFileItemWriterBuilder<Employee>()
.name("csv-salary-writer")
.resource(new FileSystemResource(outputPath))
.lineAggregator(lineAggregator)
.encoding("UTF-8")
.build();
}
@Bean
public Step writeSalarySlipToCsv (
JpaPagingItemReader<Employee> someoneReader,
FlatFileItemWriter<Employee> csvWriter
) {
return stepBuilderFactory
.get("retrieve-salary-slip-step")
.<Employee, Employee>chunk(1)
.reader(someoneReader)
.processor(employeeProcessor())
.writer(csvWriter)
.stream(someoneReader)
.build();
}
@Bean
public Job paySalaryJob(
Step writeSalarySlipToCsv
) {
return jobBuilderFactory
.get("pay-salary-job")
.incrementer(new RunIdIncrementer())
.start(writeSalarySlipToCsv)
.build();
}
}
下面是测试执行的stacktrace:
2019-06-1217:17:32.845-信息-[主要]{
b、 g.t.StepScopeIntegrationTest 45}-->步骤执行!2019-06-12
17:17:32.845-INFO-[main]{b.g.t.StepScope集成测试47
}-->Context={}/Step=检索工资单步骤2019-06-12
17:17:32.970-INFO-[main]{b.g.t.StepScope集成测试41
}-->执行前,我们有4个条目2019-06-12 17:17:33.002-
信息-[main]{b.g.t.StepScopeIntegrationTest 53}-->页面=0
2019-06-1217:17:33.002-信息-[主要]{
b、 g.t.StepScopeIntegrationTest 54}-->页面大小=1
位于的java.lang.NullPointerException
org.springframework.batch.item.database.JpaPagingItemReader.doReadPage(JpaPagingItemReader.java:192)
在
org.springframework.batch.item.database.AbstractPagingItemReader.doRead(AbstractPagingItemReader.java:108)
在
org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:89)
在
org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader$$FastClassBySpringCGLIB$$ebb633d0.invoke()
在
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
在
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
在
org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:163)
在
org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
在
org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
在
org.springframework.aop.framework.ReflectiveMethodInvocation.procedure(ReflectiveMethodInvocation.java:185)
在
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
在
org.springframework.batch.item.database.JpaPagingItemReader$$EnhancerBySpringCGLIB$$b998315d.read()
在
be.groups.test.StepScopeIntegrationTest.testReader(StepScopeIntegrationTest.java:55)
位于的sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)
invoke(NativeMethodAccessorImpl.java:62)
在
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
位于java.lang.reflect.Method.invoke(Method.java:498)
org.junit.runners.model.FrameworkMethod$1.runReflectVeCall(FrameworkMethod.java:50)
在
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
在
org.junit.runners.model.FrameworkMethod.invokeeexplosive(FrameworkMethod.java:47)
在
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
在
org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
在
org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
在
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
在
org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
在
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
在
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
位于org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
在
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)位于
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)位于
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)位于
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)位于
org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
在
org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:363)
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
位于org.junit.runner.JUnitCore.run(JUnitCore.java:137)
JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
在
intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
在
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
在
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
我使用的是h2数据库,在启动时用import.sql和schema-h2.sql脚本提供的数据填充数据库。我正在使用Spring Boot 2.0.5.RELEASE和Spring Batch Core 4.1.2.RELEASE 根据马哈茂德·本·哈辛(Mahmoud Ben Hassine)在评论中的建议,我已将我的考试课程改为:
@Slf4j
//@SpringBootTest
@SpringBatchTest
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
@ContextConfiguration(classes = {
PaySalaryJobConfiguration.class
})
@ActiveProfiles("test")
public class StepScopeIntegrationTest {
@Autowired
private JpaPagingItemReader<Employee> someoneReader;
@Autowired
private JdbcTemplate jdbcTemplate;
private StepExecution stepExecution;
@Before
public void setUp() {
log.info("Before execution we have {} entries", jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class ));
}
public StepExecution getStepExecution() {
log.info("Step Execution !");
stepExecution = MetaDataInstanceFactory.createStepExecution();
log.info("Context = {} / Step = {} ", stepExecution.getExecutionContext(), stepExecution.getStepName());
return stepExecution;
}
@Test
public void testReader() throws Exception {
log.info("Page = {}", someoneReader.getPage());
log.info("PageSize = {}", someoneReader.getPageSize());
someoneReader.open(stepExecution.getExecutionContext());
Assert.assertNotNull(someoneReader.read());
}
}
@Override
@SuppressWarnings("unchecked")
protected void doReadPage() {
EntityTransaction tx = null;
if (transacted) {
tx = entityManager.getTransaction(); // EntityManager is null...
tx.begin();
entityManager.flush();
entityManager.clear();
}//end if
@Slf4j
//@SpringBootTest
@SpringBatchTest
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
@ContextConfiguration(classes = {
PaySalaryJobConfiguration.class
})
@ActiveProfiles("test")
public class StepScopeIntegrationTest {
@Autowired
private JpaPagingItemReader<Employee> someoneReader;
@Autowired
private JdbcTemplate jdbcTemplate;
private StepExecution stepExecution;
@Before
public void setUp() {
log.info("Before execution we have {} entries", jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class ));
}
public StepExecution getStepExecution() {
log.info("Step Execution !");
stepExecution = MetaDataInstanceFactory.createStepExecution();
log.info("Context = {} / Step = {} ", stepExecution.getExecutionContext(), stepExecution.getStepName());
return stepExecution;
}
@Test
public void testReader() throws Exception {
log.info("Page = {}", someoneReader.getPage());
log.info("PageSize = {}", someoneReader.getPageSize());
someoneReader.open(stepExecution.getExecutionContext());
Assert.assertNotNull(someoneReader.read());
}
}