关于单元测试DAO的疑问

时间:2015-07-17 11:50:26

标签: java unit-testing mockito dao easymock

我正在寻找信息来构建典型DAO方法的单元测试(通过用户名等查找用户),我发现了几个使用这样的模拟的例子:http://www.christophbrill.de/de_DE/unit-testing-with-junit-and-mockito/

@Test
public void testComeGetSome() {
    // Mock the EntityManager to return our dummy element
    Some dummy = new Some();
    EntityManager em = Mockito.mock(EntityManager.class);
    Mockito.when(em.find(Some.class, 1234)).thenReturn(dummy);

    // Mock the SomeDao to use our EntityManager
    SomeDao someDao = Mockito.mock(SomeDao.class);
    Mockito.when(someDao.comeGetSome(1234)).thenCallRealMethod();
    Mockito.when(someDao.getEntityManager()).thenReturn(em);

    // Perform the actual test
    Assert.assertSame(dummy, someDao.comeGetSome(1234));
    Assert.assertNull(someDao.comeGetSome(4321));
}

在Lasse Koskela的书中也有类似的使用EasyMock而不是Mockito。

问题是:我们在这些例子中真正测试了什么?我们基本上是通过模拟告诉查询应该返回什么对象,然后断言实际上它返回了我们告诉它返回的对象。

我们不测试查询是否正确,或者它是否返回不同的对象或根本没有对象(甚至多于一个对象)。当数据库中不存在该对象时,我们无法测试它是否返回null。这一行

Assert.assertNull(someDao.comeGetSome(4321));

起作用,因为该参数没有脚本化的交互,不是因为该对象不存在。

看起来我们只是测试方法是否调用了正确的方法和对象(em.find)。

单元测试有什么意义? Java中是否有任何好的框架可以快速设置内存数据库并使用它进行测试?

2 个答案:

答案 0 :(得分:2)

你的怀疑真的有道理。实际上在大多数情况下没有必要用单元测试来测试DAO,因为单元测试处理一层,但DAO与数据库层合作。

本文解释了这个想法: http://www.petrikainulainen.net/programming/testing/writing-tests-for-data-access-code-unit-tests-are-waste/

因此我们应该使用集成测试来测试DAO和数据库层。 集成测试考虑了DAO和数据库层。

本文将为您提供Spring + Hibernate示例: https://dzone.com/articles/easy-integration-testing

答案 1 :(得分:1)

它看起来更像服务测试,而不是真正的DAO测试。 例如,我使用dbunit来测试我的DAO图层。

例如,我有Author表,其中有两个字段:idname。 我正在创建像

这样的数据集xml文件
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <AUTHOR AUTHOR_ID="1" NAME="FirstAuthor"/>
    ...
    <AUTHOR AUTHOR_ID="10" NAME="TenthAuthor"/>
</dataset>

然后在我的测试班中使用Mockito我测试我的DAO方法,如

@Test
@DatabaseSetup(value = "/dao/author/author-data.xml")
public void testFindAll() {
    List<Author> authorList = this.authorDAO.findAll();
    assertEquals(10, authorList.size());
}