使用Mockito进行Sprng批量stepscope阅读器测试 - org.springframework.batch.item.ReaderNotOpenException:阅读器必须先打开才能读取

问题描述 投票:0回答:1

我正在测试 @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
spring-boot unit-testing mockito spring-batch reader
1个回答
0
投票

您共享的代码在测试类中自动装配

JdbcCursorItemReader
(这意味着读者应该在测试上下文中定义为bean并由Spring管理),同时在
setUp
方法中手动创建bean 。这是不正确的,应该删除手动创建 bean。

参考文档中测试作用域 bean 的示例不会使用

new
运算符手动创建 bean:测试步骤作用域组件

也就是说,您遇到的错误似乎发生在调用测试之前,在开始读取数据之前确实打开了阅读器。

© www.soinside.com 2019 - 2024. All rights reserved.