如何使用Mockito来测试Java8Stream是否具有预期值



我想要测试的交互之一是类Foo应该将Stream<Changes>传递给FooListener.someChangesHappened。是否有Mockito习惯用法来验证流是否包含预期的对象?

假设您只是在验证mock实现的参数,而实际上并没有使用它,那么这里有一个自定义的Hamcrest Matcher,它将完成任务。当您需要从Stream读取多次时,它会变得很麻烦,因为Stream并不是为此而构建的。您会注意到,这个解决方案甚至需要保护自己不受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);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新