What would be a good way to compare two Stream
instances in Java 8 and find out whether they have the same elements, specifically for purposes of unit testing?
What I've got now is:
@Test
void testSomething() {
Stream<Integer> expected;
Stream<Integer> thingUnderTest;
// (...)
Assert.assertArrayEquals(expected.toArray(), thingUnderTest.toArray());
}
or alternatively:
Assert.assertEquals(
expected.collect(Collectors.toList()),
thingUnderTest.collect(Collectors.toList()));
But that means I'm constructing two collections and discarding them. It's not a performance issue, given the size of my test streams, but I'm wondering whether there's a canonical way to compare two streams.
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();
}
Collecting the stream under test (as you show) is a straightforward and effective way of performing the test. You may create the list of expected results in the easiest way available, which might not be collecting a stream.
Alternatively, with most libraries for creating mock collaborators, one could mock a Consumer
that "expects" a series of accept()
calls with particular elements. Consume the Stream
with it, and then "verify" that its configured expectations were met.
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);
}
You can assert the stream's content without creating a Stream<> expected
.
assertj has fluent and readable solutions for this.
import static org.assertj.core.api.Assertions.assertThat;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
class MyTests {
@Test
void test() {
Stream<Integer> actual = Stream.of(0, 8, 15); // your thingUnderTest
assertThat(actual).containsExactly(0, 8, 15);
}
}
Using the elementsEqual
method in the Guava library:
Iterators.elementsEqual(s1.iterator(), s2.iterator())
How to Compare Two Streams in java 8 and above: with the example of Comparing IntStream
package com.techsqually.java.language.generics.basics;
import java.util.Iterator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class TwoStreamComparision {
public static void main(String[] args) {
String a = "Arpan";
String b = "Arpen";
IntStream s1 = a.chars();
IntStream s2 = b.chars();
Iterator<Integer> s1It = s1.iterator();
Iterator<Integer> s2It = s2.iterator();
//Code to check how many characters are not equal in both the string at their Respective Position
int count = 0;
while (s2It.hasNext()){
if (!s1It.next().equals(s2It.next())){
count++;
}
}
System.out.println(count);
}
}