2016-01-15 13 views
17

Was wäre ein guter Weg, zwei Instanzen in Java 8 zu vergleichen und herauszufinden, ob sie die gleichen Elemente haben, speziell für Unit-Tests?Wie zwei Streams in Java zu vergleichen 8

Was muss ich jetzt:

@Test 
void testSomething() { 
    Stream<Integer> expected; 
    Stream<Integer> thingUnderTest; 
    // (...) 
    Assert.assertArrayEquals(expected.toArray(), thingUnderTest.toArray()); 
} 

oder alternativ:

Assert.assertEquals(
    expected.collect(Collectors.toList()), 
    thingUnderTest.collect(Collectors.toList())); 

Aber das bedeutet, dass ich die Konstruktion zwei Sammlungen und sie zu verwerfen. Angesichts der Größe meiner Teststreams ist das kein Leistungsproblem, aber ich frage mich, ob es einen kanonischen Weg gibt, zwei Streams miteinander zu vergleichen.

+0

Ich bin mir ziemlich sicher, dass es keine Möglichkeit gibt, die Ströme in eine Sammlung oder ein Array ohne Nötigung, wie Sie oben getan haben. – joecoder

+5

Fragen Sie jeweils nach einem 'iterator()' und durchlaufen Sie sie im Lockstep. –

+6

BTW, das kommt im Test-Framework für Streams selbst vor. Wir haben 18 Traversierungsmodi spezifiziert (es gibt mehr, das sind die, die wir getestet haben) und den "gleichen" Strom auf allen Wegen durchlaufen und vergleichen, dass die Ergebnisse identisch sind (Modulo-Umordnungen, die durch die Stream-Bibliothekssemantik erlaubt sind.) Siehe zum Beispiel , http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java. –

Antwort

17
static void assertStreamEquals(Stream<?> s1, Stream<?> s2) 
{ 
    Iterator<?> iter1 = s1.iterator(), iter2 = s2.iterator(); 
    while(iter1.hasNext() && iter2.hasNext()) 
     assertEquals(iter1.next(), iter2.next()); 
    assert !iter1.hasNext() && !iter2.hasNext(); 
} 
+0

Ich denke, Sie können 'BaseStream s1, BaseStream s2' verwenden, um' IntStream', 'LongStream' und' DoubleStream' zu unterstützen. –

+0

@TagirValeev - gute Idee. Und für die Performance-besessenen sollten sie 'assertStreamEquals (IntStream, IntStream)' usw. überladen. – ZhongYu

4

Das Sammeln des zu testenden Streams (wie Sie sehen) ist eine einfache und effektive Art, den Test durchzuführen. Sie können die Liste der erwarteten Ergebnisse auf die einfachste verfügbare Weise erstellen, die möglicherweise keinen Stream sammelt.

Alternativ könnte man mit den meisten Bibliotheken zum Erstellen von Schein-Kollaborateuren eine Consumer, die eine Reihe von accept() Aufrufe mit bestimmten Elementen "erwartet". Consume die Stream damit, und dann "überprüfen", dass die konfigurierten Erwartungen erfüllt wurden.

1
public static boolean equalStreams(Stream<?>...streams) { 
    List<Iterator<?>>is = Arrays.stream(streams).map(Stream::iterator).collect(Collectors.toList()); 
    while(is.stream().allMatch(Iterator::hasNext)) 
     if(is.stream().map(Iterator::next).distinct().limit(2).count()>1) return false; 
    return is.stream().noneMatch(Iterator::hasNext); 
}