我正在为一个类似数据库查询的方法编写一些简单的单元测试:它返回一个结果列表,可以使用限制(最多n个结果)和一个页面(第p组)自定义结果)。我想测试几个案例,例如:
我需要模拟返回的结果(实际名称),所以我只是使用计数器生成它们以列出“名称#1”,“名称#2”等等。我需要。每个测试看起来(大致)如:
public void testGetMockCandidatesLimited() throws Exception {
int numResults = 4;
setupMock(numResults);
results = queryFunction(...);
// Check that the expected number of results was returned
assertEquals(numResults, results.size());
// Check that the results are correct and in order
for (int i = 0; i < numResults; i++) {
assertEquals(result.get(i).getName(), "Name #" + (i + 1));
}
}
我的问题是:以这种方式“生成”预期的答案是否可以?这是一个简单的例子,但下一步是编写一个测试来编写测试以获得每个结果的第二页,我有:
final int TEST_LIMIT = 2, TEST_PAGE = 1;
// Check that the expected number of results was returned
assertEquals(numResults, results.size());
// Check that the results are correct and in order
for (int i = TEST_LIMIT * TEST_PAGE; i < TEST_LIMIT * TEST_PAGE + TEST_LIMIT; i++) {
assertEquals(result.get(i).getName(), "Name #" + (i + 1));
}
现在碰巧这个测试是“正确的”,因为我会接受我期望的值,并确保结果是“Name#3”和“Name#4”。然而,我的queryFunction也会以相同的方式计算返回哪些结果(limit * page + limit
类似的东西)。
这是令人担忧的,因为如果测试以与被测单元相同的方式生成预期答案,则不会检测该方法中是否存在错误。但是,使用常量命名输入值会使测试更具可读性,而不仅仅是插入1到4之间的魔术整数。
处理这种情况的最佳方法是,可读性和可维护性(例如,如果需要,将来会改变价值观)?
答案 0 :(得分:1)
在提出这个问题时,我想我已经说服自己解决方案是将预期值定义为常量,例如:
final int LIMIT = 2, PAGE = 1, MIN_RESULT = 3, MAX_RESULT = 4;
...然后在断言中使用这些值。这保留了命名键值的所有可读性,并且不鼓励产生预期输出的诱惑。在这种情况下,我仍然会使用循环来生成Name #MIN
和Name #MAX
之间的每个预期名称,但边界本身将是显式静态的。
这是不是很好,还是有更好的方法来处理这种重复性?