Java 我应该在单元测试时从正在测试的类中调用方法吗?
我有一个数据库助手类,它可以插入、删除、保存、连接等,我正在为此编写测试。然而,当我编写测试用例时,它应该独立于测试类吗 应该是: 1-) (你看,在这里,我使用了“保存”方法。) 2-) 哪一个是正确的或更好的?或者测试单元应该独立于其他功能 编辑:删除前添加的AssertEquals。Java 我应该在单元测试时从正在测试的类中调用方法吗?,java,unit-testing,junit,Java,Unit Testing,Junit,我有一个数据库助手类,它可以插入、删除、保存、连接等,我正在为此编写测试。然而,当我编写测试用例时,它应该独立于测试类吗 应该是: 1-) (你看,在这里,我使用了“保存”方法。) 2-) 哪一个是正确的或更好的?或者测试单元应该独立于其他功能 编辑:删除前添加的AssertEquals。 EDIT-2:在第二个选项中,应该只有一个方法是“delete”,它将独立于类中的其他方法。因此,应该有一个查询而不是contain方法。假设您也单独测试save方法,我将使用1,为了使delete测试不会在
EDIT-2:在第二个选项中,应该只有一个方法是“delete”,它将独立于类中的其他方法。因此,应该有一个查询而不是contain方法。假设您也单独测试
save
方法,我将使用1,为了使delete
测试不会在将save
的内部实现更改为使用其他机制时中断
或者,您可以在@Before
方法中插入要删除的记录,以便您只需在实际测试中使用delete
,就可以清楚地知道该方法正在测试什么
无论哪种情况,您都应该
assertEquals(2,derbyDb.contain(dateStr,word))
在删除之前,因此您知道删除
是它在删除之后为零的原因
谷歌在厕所博客上的测试有一篇与此相关的帖子: 独立于实现细节的测试更易于维护,因为每次更改实现时都不需要更改它们。它们也更容易理解,因为它们基本上充当代码示例,显示了类方法的所有不同使用方式,因此即使是不熟悉实现的人通常也应该能够通读测试以了解如何使用类 复制测试中的数据库级逻辑是测试实现。您可能需要进行以下更改:
- 重命名数据库表和列李>
- 将
类更改为使用其他底层存储—可能您需要它的内存实现,或者您无法使用JDBC连接到的东西derbyDb
如果你采取了第一种方法,你就不会。在测试中,一切都“正常工作”——或者不正常,但是您知道这是一个错误的实现,而不是一个错误的测试。后一个测试更安全,因为在第一个测试中,您有第一个方法失败的风险——if
derbyDb.save()
如果工作不正常,您可能会在测试方法上出现错误,这将是一个假阳性
另一方面,如果您对.save()
方法有一个单独的测试,那么使用第一个测试就更清楚了。毕竟,如果您的构建在一个或两个测试中失败,这并没有多大区别——仍然有代码需要修复。确保您测试了在其他测试中使用的所有方法
可能一个好的方法是只使用在以前的测试中已经测试过的方法。在这两种情况下,您都应该
assertEquals(2,derbyDb.contain(dateStr,word))
在删除之前,因此您知道删除
是它在删除之后为零的原因。如果testDelete依赖于保存
的测试方法(例如with),则第一个选项会更清楚。我会使用第二个选项-您想要测试一个特定的方法,该方法的测试应该独立于其他方法。您的示例很简单,但如果它变得更复杂,您的测试可能会变得一团糟,否则就不清楚每个测试方法究竟测试什么和依赖什么。@Jesper我知道您的意思,但请注意,在这两种情况下,测试都会调用delete
和contain
。我认为如果只有delete
正在测试中,您应该以相同的方式检查save
和contain
(通过方法或通过conn
),我认为他也不应该使用contain
,而是通过在测试方法中执行查询来检查数据库是否包含预期的内容。
@Test
public void testDelete() throws SQLException {
// Given
String dateStr = "09-May-2016";
String word = "testWord";
derbyDb.save(dateStr, word, 9);
derbyDb.save(dateStr, word, 11);
// When
assertEquals(2, derbyDb.contain(dateStr, word));
derbyDb.delete();
// then
assertEquals(0, derbyDb.contain(dateStr, word));
}
@Test
public void testDelete() throws SQLException {
// Given
String dateStr = "09-May-2016";
String word = "testWord";
PreparedStatement insertemp = conn
.prepareStatement("insert into " + tableName + "(PUBLISHDATE,WORD,FREQUENCY) values(?,?,?)");
insertemp.setString(1, dateStr);
insertemp.setString(2, word);
insertemp.setInt(3, frequency);
insertemp.executeUpdate();
// When
assertEquals(2, derbyDb.contain(dateStr, word));
derbyDb.delete();
// then
assertEquals(0, derbyDb.contain(dateStr, word));
}