JUnit 和 hamcrest:containsInAnyOrder() 可以告诉我们更多关于不匹配的信息吗?
JUnit & hamcrest: could containsInAnyOrder() tell more about the mismatch?
在使用 JUnit 和 Hamcrest Matchers 测试 Set
时,我注意到 Matchers.contains()
方法提供了一个关于测试错误的很好的线索。另一方面 Matchers.containsInAnyOrder()
差异报告几乎没有用。这是测试代码:
简单的bean:
public class MyBean {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
JUnit测试:
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyTest {
@Test
public void hamcrestTest() {
Set<MyBean> beanSet = new HashSet<MyBean>();
MyBean bean = new MyBean();
bean.setId(1);
beanSet.add(bean);
bean = new MyBean();
bean.setId(2);
beanSet.add(bean);
assertThat(beanSet, contains(
hasProperty("id", is(1)),
hasProperty("id", is(3))
));
}
}
如您所见,实际的 bean id 是 1
和 2
,而预期的是 1
和 3
,因此测试失败。
测试结果:
java.lang.AssertionError:
Expected: iterable over [hasProperty("id", is <1>), hasProperty("id", is <3>)] in any order
but: Not matched: <MyBean@4888884e
如果我切换到 Matchers.contains()
方法,那么结果会提供更多信息:
java.lang.AssertionError:
Expected: iterable containing [hasProperty("id", is <1>), hasProperty("id", is <3>)]
but: item 0: property 'id' was <2>
不幸的是,由于 Set 未排序 contains()
在这种情况下不是一个选项。
最后的问题:
在使用 hamcrest 断言 Set
时,是否有可能以某种方式获得更好的错误报告?
Hamcrest 似乎对如何报告 contains
和 containsInAnyOrder
匹配器的不匹配有不同的实现。
containsInAnyOrder
只是通过这样做为您提供项目的 toString()
价值:
mismatchDescription.appendText("Not matched: ").appendValue(item);
虽然 contains
匹配器通过委托给实际匹配器的 describeMismatch()
来做得更好:
matcher.describeMismatch(item, mismatchDescription);
因此,在这种情况下,您会看到 hasProperty
匹配器的附加信息,但在使用 containsInAnyOrder
时不会看到。
我认为在这种情况下你能做的最好的事情就是为你的 MyBean
class.
实现一个 toString()
已经有关于此问题的报告:https://github.com/hamcrest/JavaHamcrest/issues/47
在使用 JUnit 和 Hamcrest Matchers 测试 Set
时,我注意到 Matchers.contains()
方法提供了一个关于测试错误的很好的线索。另一方面 Matchers.containsInAnyOrder()
差异报告几乎没有用。这是测试代码:
简单的bean:
public class MyBean {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
JUnit测试:
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyTest {
@Test
public void hamcrestTest() {
Set<MyBean> beanSet = new HashSet<MyBean>();
MyBean bean = new MyBean();
bean.setId(1);
beanSet.add(bean);
bean = new MyBean();
bean.setId(2);
beanSet.add(bean);
assertThat(beanSet, contains(
hasProperty("id", is(1)),
hasProperty("id", is(3))
));
}
}
如您所见,实际的 bean id 是 1
和 2
,而预期的是 1
和 3
,因此测试失败。
测试结果:
java.lang.AssertionError:
Expected: iterable over [hasProperty("id", is <1>), hasProperty("id", is <3>)] in any order
but: Not matched: <MyBean@4888884e
如果我切换到 Matchers.contains()
方法,那么结果会提供更多信息:
java.lang.AssertionError:
Expected: iterable containing [hasProperty("id", is <1>), hasProperty("id", is <3>)]
but: item 0: property 'id' was <2>
不幸的是,由于 Set 未排序 contains()
在这种情况下不是一个选项。
最后的问题:
在使用 hamcrest 断言 Set
时,是否有可能以某种方式获得更好的错误报告?
Hamcrest 似乎对如何报告 contains
和 containsInAnyOrder
匹配器的不匹配有不同的实现。
containsInAnyOrder
只是通过这样做为您提供项目的 toString()
价值:
mismatchDescription.appendText("Not matched: ").appendValue(item);
虽然 contains
匹配器通过委托给实际匹配器的 describeMismatch()
来做得更好:
matcher.describeMismatch(item, mismatchDescription);
因此,在这种情况下,您会看到 hasProperty
匹配器的附加信息,但在使用 containsInAnyOrder
时不会看到。
我认为在这种情况下你能做的最好的事情就是为你的 MyBean
class.
toString()
已经有关于此问题的报告:https://github.com/hamcrest/JavaHamcrest/issues/47