对单元测试 DAO 的怀疑
doubts about unit testing DAOs
我正在寻找为典型的 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。
问题是:我们在这些示例中真正测试的是什么?我们基本上是通过模拟告诉查询应该 return 什么对象,然后断言实际上它 return 编辑了我们告诉它的对象 return。
我们不测试查询是否正确,或者 return 是不同的对象还是根本没有对象(甚至不止一个对象)。当数据库中不存在该对象时,我们无法测试它 return 是否为空。这一行
Assert.assertNull(someDao.comeGetSome(4321));
有效是因为该参数没有脚本交互,而不是因为该对象不存在。
看起来我们只是在测试该方法是否调用了正确的方法和对象 (em.find)。
单元测试的意义何在? Java有什么好的框架可以快速建立内存数据库并用它进行测试吗?
它看起来更像是服务测试,而不是真正的 DAO 测试。
例如,我正在使用 dbunit
来测试我的 DAO 层。
例如,我有 Author
table 和 2 个字段:id
和 name
。
我正在创建数据集 xml 文件,例如
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<AUTHOR AUTHOR_ID="1" NAME="FirstAuthor"/>
...
<AUTHOR AUTHOR_ID="10" NAME="TenthAuthor"/>
</dataset>
然后在我的测试中 class 使用 Mockito
我正在测试我的 DAO 方法,例如
@Test
@DatabaseSetup(value = "/dao/author/author-data.xml")
public void testFindAll() {
List<Author> authorList = this.authorDAO.findAll();
assertEquals(10, authorList.size());
}
你的质疑很有道理。其实在大多数情况下不需要用单元测试来测试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
我正在寻找为典型的 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。
问题是:我们在这些示例中真正测试的是什么?我们基本上是通过模拟告诉查询应该 return 什么对象,然后断言实际上它 return 编辑了我们告诉它的对象 return。
我们不测试查询是否正确,或者 return 是不同的对象还是根本没有对象(甚至不止一个对象)。当数据库中不存在该对象时,我们无法测试它 return 是否为空。这一行
Assert.assertNull(someDao.comeGetSome(4321));
有效是因为该参数没有脚本交互,而不是因为该对象不存在。
看起来我们只是在测试该方法是否调用了正确的方法和对象 (em.find)。
单元测试的意义何在? Java有什么好的框架可以快速建立内存数据库并用它进行测试吗?
它看起来更像是服务测试,而不是真正的 DAO 测试。
例如,我正在使用 dbunit
来测试我的 DAO 层。
例如,我有 Author
table 和 2 个字段:id
和 name
。
我正在创建数据集 xml 文件,例如
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<AUTHOR AUTHOR_ID="1" NAME="FirstAuthor"/>
...
<AUTHOR AUTHOR_ID="10" NAME="TenthAuthor"/>
</dataset>
然后在我的测试中 class 使用 Mockito
我正在测试我的 DAO 方法,例如
@Test
@DatabaseSetup(value = "/dao/author/author-data.xml")
public void testFindAll() {
List<Author> authorList = this.authorDAO.findAll();
assertEquals(10, authorList.size());
}
你的质疑很有道理。其实在大多数情况下不需要用单元测试来测试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