使用Mockito为JdbcTemplate模拟数据源

4
我是一名有用的助手,可以为您翻译文本。

我正在尝试测试Spring项目中的一个类。我希望在测试类中进行尽可能多的更改,而不是在dao类中进行更改,以便我不必因为更改而重新测试所有内容。

我正在处理的类具有一个JdbcTemplate template类变量,它是通过以下方式实例化的:

setJdbcTemplate(DataSource dataSource) {
    this.template = new JdbcTemplate(dataSource);
}

我想测试的方法使用template.query(<code>)来运行一个定义好的SQL查询,并将结果返回到一个列表中。

在我的测试案例中,我创建了以下内容,但我不确定如何使用它。我能否使用Mockito使下面的代码返回一定的字符串列表?

DataSource mockedDataSrc = Mockito.mock(DataSource.class);
customerClassDao.setJdbcTemplate(mockedDataSrc); 

我能否使用when命令或其他命令来设置我想要返回给JdbcTemplate的.query调用的内容呢?

2个回答

4
如果你在测试DAO,则模拟数据源完全没有意义。你在测试什么?你需要创建一个与数据库交互的DAO。
一旦你完成了这个步骤,就可以在测试使用它的服务时,模拟基于接口的DAO。你已经测试过DAO了;在测试服务时没有必要重做它。
如果在测试DAO时模拟数据源,我会说你正在偏离正确的轨道。

1
在DAO中测试RowMapper或其他代码,它可以构建除基本查询响应之外的其他内容是非常有用的。 - DomenicDatti
如果 DAO 能够正常工作,你可以在 DAO 测试中模拟 ResultSet 或者包含 RowMapper。 - duffymo

3
由于您无法控制 JdbcTemplate 的实现,因此无法这样做。您应该注入依赖项 JdbcTemplate,然后再模拟 JdbcTemplate
这个困难指出了您代码中的一个问题。您的代码依赖于 JdbcTemplate 的具体实例。如果您改为使用依赖注入,则耦合性将更低。
由于您不想修改正在测试的系统,因此可以这样做:
template 字段更改为包保护(即删除 private 关键字)。然后,在实例化要测试的类之后,将其设置为 mock(JdbcTemplate.class)。现在,您将能够像最初想要的那样直接在 JdbcTemplate 上使用 when 和 verify。
因此,您要测试的类将如下所示:
public class SystemUnderTest {

JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
    }

}

而你的测试将会做到以下几点:
@Before
public void setUp() {
    SystemUnderTest sut = new SystemUnderTest();
    sut.jdbcTemplate = mock(JdbcTemplate.class);                
}

// ...

数据源是通过applicationContext.xml通过Spring注入的。我不确定为什么他们选择只注入数据源而不是jdbcTemplate,但我想测试我编写的方法,而不必改变/重构太多其他代码。因为我的更改实际上只影响了一个方法中的1个SQL调用。 - Kyle
如果您现在模拟数据源并传递它,您的测试是否会崩溃?如果不会,那么有一些事情您可以做,但我需要先知道这个。 - Daniel Kaplan
它不会崩溃,只是显示成功。我不知道该从哪里开始,因为我对Mockito/jUnit非常陌生。我已经谷歌了几个小时,除了我上面展示的两行代码之外,还没有完全弄清楚该怎么做。 - Kyle
1
谢谢,这让我朝着正确的方向前进了。非常感激。 - Kyle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接