我只是想知道人们如何进行单元测试并断言“预期”集合与“实际”集合相同/相似(顺序并不重要)。
为了执行这个断言,我编写了简单的断言 API:-
public void assertCollection(Collection<?> expectedCollection, Collection<?> actualCollection) {
assertNotNull(expectedCollection);
assertNotNull(actualCollection);
assertEquals(expectedCollection.size(), actualCollection.size());
assertTrue(expectedCollection.containsAll(actualCollection));
assertTrue(actualCollection.containsAll(expectedCollection));
}
嗯,它有效。如果我只断言一堆整数或字符串,这很简单。例如,如果我试图断言 Hibernate 域的集合,这也可能会非常痛苦。 collection.containsAll(..) 依赖 equals(..) 来执行检查,但我总是覆盖我的 Hibernate 域中的 equals(..) 以仅检查业务 key (这是在Hibernate 网站),而不是该域的所有字段。当然,只检查业务键是有意义的,但有时我真的想确保所有字段都正确,而不仅仅是业务键(例如,新的数据输入记录)。因此,在这种情况下,我不能乱用 domain.equals(..) 并且似乎我需要实现一些比较器来仅用于单元测试目的,而不是依赖于 collection.containsAll(..)。
我可以在这里利用一些测试库吗?您如何测试您的 Collection ?
谢谢。
最佳答案
我不确定您使用的是哪个版本的 JUnit,但最近的版本有一个 assertThat
方法,它采用 Hamcrest Matcher作为论据。它们是可组合的,因此您可以构建关于集合的复杂断言。
例如,如果你想断言集合 A
包含集合 B
中的每个元素,你可以这样写:
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;
import static org.hamcrest.core.IsCollectionContaining.*;
import static org.hamcrest.collection.IsCollectionWithSize.*;
import org.hamcrest.beans.SamePropertyValuesAs;
public class CollectionTests {
/*
* Tests that a contains every element in b (using the equals()
* method of each element) and that a has the same size as b.
*/
@Test
public void test() {
Collection<Foo> a = doSomething();
Collection<Foo> b = expectedAnswer;
assertThat(a, both(hasItems(b)).and(hasSize(b.size())));
}
/*
* Tests that a contains every element in b (using introspection
* to compare bean properties) and that a has the same size as b.
*/
@Test
public void testBeans() {
Collection<Foo> a = doSomething();
Collection<Foo> b = expectedAnswer;
Collection<Matcher<Foo>> bBeanMatchers =
new LinkedList<Matcher<Foo>>();
// create a matcher that checks for the property values of each Foo
for(Foo foo: B)
bBeanMatchers.add(new SamePropertyValuesAs(foo));
assertThat(a, both(hasItems(bBeanMatchers)).and(hasSize(b.size())))
}
}
第一个测试只是在每个对象上使用 equalTo() 匹配器(它将委托(delegate)给您的 equals 实现)。如果这还不够强大,您可以使用第二种情况,它将使用 getter 和 setter 来比较每个元素。最后,您甚至可以编写自己的匹配器。 Hamcrest 包没有提供按字段匹配的匹配器(与匹配 bean 属性相反),但编写 FieldMatcher 很简单(确实是一个很好的练习)。
Matchers 一开始有点奇怪,但是如果你按照他们的例子让新的 Matchers 有一个返回匹配器的静态方法,你可以做一堆 import static
s 和你的代码基本上读起来像一个英文句子(“断言 a 都具有 b 中的项目并且具有与 b 相同的大小”)。您可以使用这些东西构建一个令人印象深刻的 DSL,并使您的测试代码更加优雅。
关于java - 对集合进行单元测试的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2922879/