2016-04-06 8 views
0

Der folgende Code soll natürlichere Behauptungen über die Größe eines Streams ermöglichen.Erstellen eines Matcher <Stream> für jUnit

Matcher<Stream> hasCount(int count) { 
    return new TypeSafeDiagnosingMatcher<Stream>() { 
     protected boolean matchesSafely(Stream stream, Description desc) { 
      long streamCount = stream.count(); 
      if (streamCount == count) { 
       return true; 
      } else { 
       desc.appendText("count ").appendValue(streamCount); 
       return false; 
      } 
     } 

     public void describeTo(Description desc) { 
      desc.appendText("count ").appendValue(count); 
     } 
    }; 
} 

Dies ermöglicht Aussagen wie:

assertThat(getWidgetStream(), hasCount(52)); 

Es funktioniert gut, wenn die Behauptung Pässe, aber wenn es (zB assertThat(Stream.empty(), hasCount(1));) nicht gibt sie den Fehler „Strom bereits bei oder geschlossen betrieben wurde“ eher als die erwartete Beschreibung "erwartet: count < 1> hatte: count < 0>".

Als ich die Quelle für TypeSafeDiagnosingMatcher überprüfte, fand ich, dass matchesSafely von und describeMismatch aufgerufen wird. Also nimmt Hamcrest an, dass matchesSafely idempotent ist, was meiner nicht ist.

Gibt es eine Möglichkeit, dieses Problem zu umgehen?

Antwort

0

Eine Lösung, die ich entdeckt habe, ist, das Ergebnis zwischen den Aufrufen zu speichern.

return new TypeSafeDiagnosingMatcher<Stream>() { 
    private Optional<Long> streamCount = Optional.empty(); 

    protected boolean matchesSafely(Stream stream, Description desc) { 
     if (!streamCount.isPresent()) 
      streamCount = Optional.of(stream.count()); 
     if (streamCount.get() == count) { 
      return true; 
     } else { 
      desc.appendText("has count ").appendValue(streamCount.get().intValue()); 
      return false; 
     } 
    } 
}; 

Dies funktioniert, ist aber nicht besonders elegant.

+0

As 'mtachedSafely' wird ein zweites Mal nach' shareTo' aufgerufen, um die Beschreibung für den 'but: ...' -Teil zu erzeugen. Es scheint der richtige Weg zu sein. – SubOptimal

+0

@SubOptimal ja Ich vermute, das ist die einfachste Lösung, aber es scheint eine kleine Lücke in Hamcrest zu sein, wenn man annimmt, dass 'matchesSafely' zweimal aufgerufen werden kann. – sprinter

+1

Aber es sieht so aus [IsCollectionContainingTest.java] (https://github.com/hamcrest/JavaHamcrest/blob/master/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java#L89) das ist der beabsichtigte Weg. – SubOptimal