2

我正在编写一些自定义匹配器来简化 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)。

你们如何测试匹配器?提前致谢。

4

3 回答 3

2

我正在使用 assertThat 来测试匹配功能。

@Test
public void returnsMatchedGivenNoneConstraintViolations() throws Excetpion {
     assertThat(someObject, matcher);
}  

@Test
public void returnsMismatchedGivenSomeConstraintViolations() throws Excetpion {
     assertThat(someObject, not(matcher));
}   
于 2013-08-21T15:46:25.340 回答
0

To answer your follow-up question about testing the description, I don't see that as necessary. I consider it sufficient to write your returnsConstraintViolationsFoundWhenMismatched test like this

@Test(expected=Exception.class)
public void returnsConstraintViolationsFoundWhenMismatched() {
  // Use the matcher in a way that causes an exception to be thrown
}

The important verification is that the proper exception was thrown. Testing the content of the actual message and is not adding any value to your test suite. You can just trust that the Hamcrest library is doing the right thing with the text you append to the description.

于 2014-03-15T03:30:08.330 回答
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"));
  }
于 2018-04-04T16:55:18.907 回答