我正在测试 @stepscope JDBCCUrsorIteamReader 但出现以下错误。我在开始阅读之前打开阅读器,但它的阅读器仍然没有打开。我想模拟数据库调用。
如何在模拟数据库调用时使其工作
org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.
读者代码
@Bean
@StepScope
public JdbcCursorItemReader<LimsExternalLinkDTO> findExternalLinksReader(@Value("#{jobParameters['bookId'] != null ? jobParameters['bookId'] : 0}") int bookId) {
JdbcCursorItemReader<LimsExternalLinkDTO> reader = new JdbcCursorItemReader<>();
reader.setDataSource(dataSource);
reader.setSql(FIND_EXTERNAL_LINKS);
reader.setPreparedStatementSetter(ps -> {
ps.setInt(1, bookId);
ps.setInt(2, bookId);
});
reader.setRowMapper(new BeanPropertyRowMapper<>(LimsExternalLinkDTO.class));
reader.setFetchSize(BATCH_SIZE);
reader.setQueryTimeout(REQUEST_TIMEOUT);
return reader;
}
阅读器测试代码
@ContextConfiguration
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
StepScopeTestExecutionListener.class })
@RunWith(SpringJUnit4ClassRunner.class)
class ReaderConfigurationTest {
@Autowired
private JdbcCursorItemReader<LimsExternalLinkDTO> itemReader;
@BeforeEach
void setUp() throws SQLException {
itemReader = new JdbcCursorItemReader<>();
// itemReader.setDataSource(ds);
}
@AfterEach
void tearDown() {
}
@Test
void testUsesCurrentTransaction() throws Exception {
DataSource ds = Mockito.mock(DataSource.class);
Connection con = Mockito.mock(Connection.class);
Mockito.when(con.getAutoCommit()).thenReturn(false);
PreparedStatement ps = Mockito.mock(PreparedStatement.class);
Mockito.when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT))
.thenReturn(ps);
Mockito.when(ds.getConnection()).thenReturn(con);
Mockito.when(ds.getConnection()).thenReturn(con);
con.commit();
PlatformTransactionManager tm = new JdbcTransactionManager(ds);
TransactionTemplate tt = new TransactionTemplate(tm);
final JdbcCursorItemReader<LimsExternalLinkDTO> reader = new JdbcCursorItemReader<>();
reader.setDataSource(new ExtendedConnectionDataSourceProxy(ds));
reader.setUseSharedExtendedConnection(true);
reader.setSql("select foo from bar");
final ExecutionContext ec = new ExecutionContext();
ec.put("externalLinks",mockedLimsExternalLinkData());
tt.execute(status -> {
reader.open(ec);
try {
reader.read();
} catch (Exception e) {
throw new RuntimeException(e);
}
reader.close();
return null;
});
}
public List<LimsExternalLinkDTO> mockedLimsExternalLinkData() {
List<LimsExternalLinkDTO> linksList = new ArrayList<>();
LimsExternalLinkDTO limsExternalLink = new LimsExternalLinkDTO();
limsExternalLink.setExternalLink("https://www.google.com");
limsExternalLink.setId(1);
limsExternalLink.setBookName("Test Book");
limsExternalLink.setStatus(null);
limsExternalLink.setBookId(316);
limsExternalLink.setChapterId(6);
limsExternalLink.setChapterName("Abacavir");
limsExternalLink.setSectionId(1);
limsExternalLink.setSectionName("Section1");
limsExternalLink.setFieldId(1);
linksList.add(limsExternalLink);
return linksList;
}
}
日志-
11:23:07.607 [Test worker] DEBUG org.springframework.jdbc.support.JdbcTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
11:23:07.613 [Test worker] DEBUG org.springframework.jdbc.support.JdbcTransactionManager - Acquired Connection [Mock for Connection, hashCode: 718512571] for JDBC transaction
11:23:07.617 [Test worker] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
11:23:07.630 [Test worker] DEBUG org.springframework.transaction.support.TransactionTemplate - Initiating transaction rollback on application exception
java.lang.RuntimeException: org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.
at com.lexi.lims.reports.externallinks.batch.reader.ReaderConfigurationTest.lambda$testUsesCurrentTransaction$0(ReaderConfigurationTest.java:89)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at com.lexi.lims.reports.externallinks.batch.reader.ReaderConfigurationTest.testUsesCurrentTransaction(ReaderConfigurationTest.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.
at org.springframework.batch.item.database.AbstractCursorItemReader.doRead(AbstractCursorItemReader.java:497)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:93)
at com.lexi.lims.reports.externallinks.batch.reader.ReaderConfigurationTest.lambda$testUsesCurrentTransaction$0(ReaderConfigurationTest.java:87)
... 85 common frames omitted
11:23:07.637 [Test worker] DEBUG org.springframework.jdbc.support.JdbcTransactionManager - Initiating transaction rollback
11:23:07.638 [Test worker] DEBUG org.springframework.jdbc.support.JdbcTransactionManager - Rolling back JDBC transaction on Connection [Mock for Connection, hashCode: 718512571]
11:23:07.638 [Test worker] DEBUG org.springframework.jdbc.support.JdbcTransactionManager - Releasing JDBC Connection [Mock for Connection, hashCode: 718512571] after transaction
您共享的代码在测试类中自动装配
JdbcCursorItemReader
(这意味着读者应该在测试上下文中定义为bean并由Spring管理),同时在setUp
方法中手动创建bean 。这是不正确的,应该删除手动创建 bean。
参考文档中测试作用域 bean 的示例不会使用
new
运算符手动创建 bean:测试步骤作用域组件。
也就是说,您遇到的错误似乎发生在调用测试之前,在开始读取数据之前确实打开了阅读器。