Как я могу использовать Mockito, чтобы проверить, что поток Java 8 имел ожидаемые значения?



Одно из взаимодействий, которое я хочу проверить, состоит в том, что класс Foo должен передать Stream<Changes> в FooListener.someChangesHappened. Существует ли идиома Mockito, чтобы проверить, что поток содержит ожидаемые объекты?

561   1  

1 ответ:

Предполагая, что вы просто проверяете аргумент для макетной реализации, а на самом деле не используете его, вот пользовательский Hamcrest Matcher, который выполнит эту работу. Он становится волосатым, когда вам нужно прочитать из Stream более одного раза, потому что Streams не созданы для этого. Вы заметите, что это решение даже должно защитить себя от вызова JUnit matches более одного раза.

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

    Ничего не найдено.