我正在编写一些自定义匹配器来简化junit断言。其中大多数扩展了TypeSafeMatcher,所以我只需要覆盖三种方法:
public class NoneConstraintViolationMatcher<T> extends
TypeSafeMatcher<Set<ConstraintViolation<T>>> {
@Override
public void describeTo(Description description) {
description.appendText("None constraint violations found");
}
@Override
protected void describeMismatchSafely(Set<ConstraintViolation<T>> item,
Description mismatchDescription) {
mismatchDescription.
appendText("Unexpected constraint violation found, but got ");
mismatchDescription.appendValueList("", ",", "", item);
}
@Override
protected boolean matchesSafely(Set<ConstraintViolation<T>> item) {
return item.isEmpty();
}
}
我的问题是如何测试它们?我目前的解决方案是
public class NoneConstraintViolationMatcherUnitTests {
private NoneConstraintViolationMatcher<Object> matcher =
new NoneConstraintViolationMatcher<Object>();
@Test
public void returnsMatchedGivenNoneConstraintViolations() throws Excetpion {
assertTrue(matcher.matches(.....));
}
@Test
public void returnsMismatchedGivenSomeConstraintViolations() throws Excetpion {
assertThat(matcher.matches(.....), is(false));
}
@Test
public void returnsConstraintViolationsFoundWhenMismatched()
throws Exception {
StringBuilder out = new StringBuilder();
//I don't find anything could be used to assert in description
StringDescription description = new StringDescription(out);
matcher.describeMismatch(..someCvx, description);
assertThat(out.toString(),
equalTo("Unexpected constraint violation found, but got "));
}
}
我想到的另一个解决方案是编写junit测试并使用@Rule ExpectedException(将handleAssertionError设置为true)。
你们如何测试匹配器?提前谢谢。
答案 0 :(得分:2)
我正在使用assertThat来测试匹配功能。
@Test
public void returnsMatchedGivenNoneConstraintViolations() throws Excetpion {
assertThat(someObject, matcher);
}
@Test
public void returnsMismatchedGivenSomeConstraintViolations() throws Excetpion {
assertThat(someObject, not(matcher));
}
答案 1 :(得分:0)
要回答有关测试说明的后续问题,我认为没有必要。我认为写这样的returnsConstraintViolationsFoundWhenMismatched
测试就足够了
@Test(expected=Exception.class)
public void returnsConstraintViolationsFoundWhenMismatched() {
// Use the matcher in a way that causes an exception to be thrown
}
重要的验证是抛出了适当的异常。测试实际消息的内容,而不是向测试套件添加任何值。您可以相信Hamcrest库正在使用您附加到描述中的文本做正确的事情。
答案 2 :(得分:0)
我编写了在断言中调用匹配器方法的单元测试。我认为@Factory对大多数人都有帮助。
这是匹配器:
public class ContainsIgnoringCaseMatcher extends TypeSafeMatcher<String> {
private List<String> segmentsToMatch;
public ContainsIgnoringCaseMatcher(String subString, String... additional) {
Preconditions.checkArgument(subString != null && !subString.isEmpty());
segmentsToMatch = Lists.newArrayList(subString);
if (additional != null) {
segmentsToMatch.addAll(Arrays.asList(additional));
}
}
@Override
protected boolean matchesSafely(String fullText) {
return segmentsToMatch.stream()
.allMatch(v -> StringUtils.containsIgnoreCase(fullText, v));
}
@Override
public void describeTo(Description description) {
description.appendText(String.format("containing each %s", segmentsToMatch));
}
@Factory
public static Matcher<String> containsIgnoringCase(String subString, String... additionalStrings) {
return new ContainsIgnoringCaseMatcher(subString, additionalStrings);
}
@Factory
public static Matcher<String> containsIgnoringCase(List<String> subStrings) {
String first = subStrings.get(0);
if (subStrings.size() > 1) {
List<String> subList = subStrings.subList(1, subStrings.size());
String[] additional = subList.toArray(new String[subList.size() - 1]);
return new ContainsIgnoringCaseMatcher(first, additional);
} else {
return new ContainsIgnoringCaseMatcher(first);
}
}
}
单元测试方法如下所示:
@Test
public void shouldAllowSubstringMatchOfExpected() {
assertThat("EXPECTED_ITEM", containsIgnoringCase("expected_"));
}
@Test(expected = AssertionError.class)
public void shouldNotAllowSubstringMatchOfFound() {
assertThat("EXPECTED_", containsIgnoringCase("EXPECTED_ITEM"));
}
@Test
public void shouldAllowNegatedAssert() {
assertThat("EXPECTED_", not(containsIgnoringCase("EXPECTED_ITEM")));
}
@Test(expected = AssertionError.class)
public void shouldNotAllowMismatch() {
assertThat("ab", containsIgnoringCase("ba"));
}