2016-01-15 10 views
17

Quale sarebbe un buon modo per confrontare due istanze di Stream in Java 8 e scoprire se hanno gli stessi elementi, specificamente ai fini del test dell'unità?Come confrontare due stream in Java 8

Quello che ho ora è:

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

o in alternativa:

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

Ma questo significa che sto costruendo due collezioni e scartarli. Non è un problema di prestazioni, data la dimensione dei miei stream di test, ma mi chiedo se c'è un modo canonico per confrontare due flussi.

+0

Sono abbastanza sicuro che non v'è alcun modo senza costringere i flussi in una collezione o un array come avete fatto in precedenza. – joecoder

+5

Chiedete a ciascuno per un 'iterator()', e li attraversa in un attimo. –

+6

BTW, questo emerge nel framework di testing per gli stessi Streams. Abbiamo specificato 18 modalità di attraversamento (ce ne sono di più, queste sono quelle che abbiamo testato) e attraversiamo lo stesso flusso tutti i modi e confrontiamo i risultati in modo identico (riordino del modulo consentito dalla semantica della libreria di flusso.) Vedi, per esempio , http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java. –

risposta

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

Penso che si possa usare 'BaseStream s1, BaseStream s2' per supportare' IntStream', 'LongStream' e' DoubleStream'. –

+0

@TagirValeev - buona idea. E per l'ossessionato dalle prestazioni, dovrebbero sovraccaricare 'assertStreamEquals (IntStream, IntStream)' ecc. – ZhongYu

4

La raccolta del flusso in prova (come mostrato) è un modo semplice ed efficace per eseguire il test. È possibile creare l'elenco dei risultati previsti nel modo più semplice disponibile, che potrebbe non essere la raccolta di un flusso.

In alternativa, con la maggior parte delle librerie per la creazione di collaboratori fittizi, si può prendere in giro uno Consumer che "si aspetta" una serie di chiamate accept() con elementi particolari. Consume il Stream con esso e quindi "verificare" che le sue aspettative configurate sono state soddisfatte.

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