2016-01-15 44 views
17

Jaki byłby dobry sposób porównania dwóch instancji Stream w języku Java 8 i ustalenie, czy mają one te same elementy, w szczególności w celu testowania jednostek?Jak porównać dwa strumienie w języku Java 8

Co mam teraz jest:

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

lub alternatywnie:

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

Ale to oznacza, że ​​jestem konstruowania dwa zbiory i ich wyrzuceniem. Nie jest to problem z wydajnością, biorąc pod uwagę rozmiar moich strumieni testowych, ale zastanawiam się, czy istnieje kanoniczny sposób porównania dwóch strumieni.

+0

jestem całkiem pewny, nie ma sposobu, bez zmuszania strumienie do kolekcji lub tablicy, jak zrobiliśmy powyżej. – joecoder

+5

Pytaj o 'iterator()' i przemierzaj je w lockstepie. –

+6

BTW, pojawia się w ramach testowania dla samych strumieni. Określiliśmy 18 trybów przejścia (jest ich więcej, są to te, które testowaliśmy) i przechodzimy przez "ten sam" strumień na wszystkie sposoby i porównujemy, że wyniki są identyczne (renowacje modulo dozwolone przez semantykę biblioteki strumieniowej.) Zobacz na przykład , http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java. –

Odpowiedz

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

Myślę, że możesz użyć 'BaseStream s1, BaseStream s2' do obsługi również' IntStream', 'LongStream' i' DoubleStream'. –

+0

@TagirValeev - dobry pomysł. A w przypadku obsesji na punkcie wydajności powinni przeciążyć 'assertStreamEquals (IntStream, IntStream)' itd. – ZhongYu

4

Zbieranie strumienia w trakcie testu (jak pokazano) jest prostym i skutecznym sposobem wykonania testu. Możesz utworzyć listę oczekiwanych wyników w najprostszy dostępny sposób, który może nie gromadzić strumienia.

Alternatywnie, w przypadku większości bibliotek do tworzenia próbnych współpracowników, można kpić z Consumer, który "oczekuje" serii wywołań accept() z poszczególnymi elementami. Consume the Stream z nim, a następnie "sprawdź", czy spełnione są skonfigurowane oczekiwania.

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); 
}