【问题标题】:Using mocked dataSource bean when testing Camel route测试 Camel 路由时使用模拟的 dataSource bean
【发布时间】:2020-09-22 14:09:16
【问题描述】:

我在 spring xml 中定义了一个 dataSource bean,如下所示

<bean id="apacheBasicDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" >
    <property name="url" value="jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = myservice)))" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
    ...
</bean>

现在我想测试一个休息路线,它通过在 groovy 脚本中调用存储过程来完成他的工作

<get uri="/utils/foo" produces="text/xml">
    <route id="utils.foo">
        <setBody>
            <groovy>
                import groovy.sql.Sql
                def sql = Sql.newInstance(camelContext.getRegistry().lookupByName('apacheBasicDataSource'))
                res = request.getHeader('invalues').every { invalue ->
                    sql.call("{? = call my_pkg.mapToSomeValue(?)}", [Sql.VARCHAR, invalue]) {
                        outValue -> do some stuff..
                    }
                }
                sql.close()
                new StringBuilder().append(
                    some stuff..
                )
            </groovy>
        </setBody>
    </route>
</get>

我的测试类如下,所以现在可以工作了

@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration(locations = {"classpath:camel.xml"})
public class EdiapiApplicationNewTest {

    @Autowired
    private CamelContext context;

    @MockBean private DataSource dataSource;
    @Mock private CallableStatement callableStatement;
    @Mock private Connection connection;
    @Mock private ResultSet resultSet;

    @Test
    public void testSimple() throws Exception {

        when(callableStatement.getResultSet()).thenReturn(resultSet);
        when(dataSource.getConnection()).thenReturn(connection);
        when(connection.prepareCall(anyString())).thenReturn(callableStatement);

        context.getRegistry().bind("apacheBasicDataSource", dataSource);

        TestRestTemplate restTemplate = new TestRestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:8080/utils/foo?invalues=foo,bar", String.class);
        Assert.assertEquals("<value>false</value>", response.getBody());
    }
}

但我希望能够使用一些自定义值填充模拟的 ResultSet 以进行测试(此时它返回 null)
我尝试过类似的东西

when(resultSet.next()).thenReturn(true).thenReturn(false);
when(resultSet.getString(anyInt())).thenReturn("some value");

没有成功。有人可以给我一个提示吗? 谢谢!

【问题讨论】:

  • 你能展示你的测试课吗?当您调用 REST API 或骆驼上下文加载时出现上述错误?
  • 我实际上已经在解决方案方面取得了真正的进展,所以我已经根据它更新了问题
  • 后续调用nex()不返回false?如果这是问题所在,那么您检查 mockito 的版本。 javadoc.io/doc/org.mockito/mockito-core/2.8.9/org/mockito/…。或者你可以像这个例子一样使用内部计数器stackoverflow.com/questions/8088179/…
  • @EscaTran 感谢您提供有用的链接,但问题是 groovy 闭包中的 outValue 总是变为 null,即使我没有连续的 sql 调用

标签: spring-boot unit-testing groovy mocking apache-camel


【解决方案1】:

我终于找到了问题的根源以及解决方案。
首先, void call 方法应该用 doAnswer 模拟,而不是 thenReturn (显然)。
其次,我处理的是存储函数,所以没有在callableStatement上调用getResultSet方法,而是调用了getObject方法,所以这是应该被嘲笑为

when(callableStatement.getObject(1)).thenAnswer(inv -> "some custom value");

【讨论】:

    猜你喜欢
    • 2017-07-05
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    相关资源
    最近更新 更多