Как я могу использовать Mockito, чтобы проверить, что поток Java 8 имел ожидаемые значения?
Одно из взаимодействий, которое я хочу проверить, состоит в том, что класс Foo должен передать Stream<Changes> в FooListener.someChangesHappened. Существует ли идиома Mockito, чтобы проверить, что поток содержит ожидаемые объекты?
1 ответ:
Предполагая, что вы просто проверяете аргумент для макетной реализации, а на самом деле не используете его, вот пользовательский Hamcrest
Matcher, который выполнит эту работу. Он становится волосатым, когда вам нужно прочитать изStreamболее одного раза, потому чтоStreams не созданы для этого. Вы заметите, что это решение даже должно защитить себя от вызова JUnitmatchesболее одного раза.import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.not; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) public class Foo { @Mock FooListener fooListener; @Before public void happen() { fooListener.someChangesHappened(Stream.of(Changes.ONE, Changes.TWO, Changes.THREE)); } @Test public void contains() { verify(fooListener).someChangesHappened(argThat(streamThat(hasItem(Changes.TWO)))); } @Test public void doesNotContain() { verify(fooListener).someChangesHappened(argThat(streamThat(not(hasItem(Changes.FOUR))))); } private static <T> Matcher<Stream<T>> streamThat(Matcher<Iterable<? super T>> toMatch) { return new IterableStream<>(toMatch); } private interface FooListener { void someChangesHappened(Stream<Changes> stream); } private enum Changes { ONE, TWO, THREE, FOUR } private static class IterableStream<T> extends TypeSafeMatcher<Stream<T>> { Matcher<Iterable<? super T>> toMatch; List<T> input = null; public IterableStream(Matcher<Iterable<? super T>> toMatch) { this.toMatch = toMatch; } @Override protected synchronized boolean matchesSafely(Stream<T> item) { // This is to protect against JUnit calling this more than once input = input == null ? item.collect(Collectors.toList()) : input; return toMatch.matches(input); } @Override public void describeTo(Description description) { description.appendText("stream that represents "); toMatch.describeTo(description); } } }
Comments