假设我有以下(Java)代码:
class MyObject {
private int demo;
/* ...further properties... */
/* ...getters, setters... */
}
class TestMe {
public static Set<MyObject> processAll(Set<MyObject> input) {
Set<MyObject> result = new HashSet<>();
for(final MyObject entry : input) {
result.add(process(input));
}
return result;
}
private static MyObject process(MyObject input) {
MyObject result = new MyObject();
result.setDemo(input.getDemo() + 1);
return result;
}
}
现在我想为这段代码编写一个测试。为过程方法编写测试很容易。生成的Object应该具有“demo”的值,该值比输入Object大1并且输入对象未更改。由于该方法是私有的,我还是希望避免测试该方法。
但是我想测试processAll方法是否使用空集(简单),使用集合中的一个条目(也很简单)并使用集合中的多个元素(这是我的问题)。 / p>
因为结果是一个Set,所以processAll结果中元素的顺序是未定义的,我不能简单地测试第一个元素是X而第二个元素是Y.我不能使用一些简单的actual.containsAll(expected) && expected.containsAll(actual)
魔法,因为如果MyObject只检查身份的equals方法(并且更改它没有意义)。
我尝试通过编写自己的Comparator对processAll的输入和输出进行排序,将所有元素添加到SortedSet然后迭代两个集合,假设output-1的demo属性等于输入。但我发现我的断言代码变得越来越大,难以理解。
有没有“最佳实践” - 处理这种情况?
答案 0 :(得分:1)
您提到使用containsAll
的难度。这不是检查集合内容的唯一方法。您也可以遍历其成员,在找到预期对象时设置标志,然后在循环检查后设置所有标志。
答案 1 :(得分:0)
我尝试在单元测试方面务实。
您可以对“set is empty”案例进行简单测试。
您可以对“set contains one element”进行简单测试。该测试涵盖了转换和循环。
您可以进行一项简单的测试,检查输出的大小是否等于输入的大小。
现在,您的所有代码都已涵盖,另外一项测试只能确保您的代码不会对具有多个元素的集合执行不同的操作。但是这样一个问题的可能性非常接近于0.所以这样一个复杂的测试不会增加任何有价值的东西,但很难理解和维护。即使您对10个元素进行了测试,也不会涵盖这种情况(也非常不可能),其中代码会对具有11个元素的集合执行不同的操作。
答案 2 :(得分:0)
如果你真的需要复杂的断言逻辑,你可能想要以Hamcrest Matcher的形式编写那个逻辑,而不是直接用它来混淆你的测试代码。
可能是Hamcrest提供的标准matchers之一对你很有用,尽管你似乎对标准集比较技术有困难,但似乎不太可能。
如果您使用的是最新版本的JUnit,它可能包含这些版本,您可以使用JUnit assertThat方法。