流是动态数据,如何做单元测试? StepVerifier通过订阅流,然后消费其产生的信号,逐个比较元素、错误信号、完成信号等,从而解决单元测试问题。
基本用法
先发射1,然后发射2,最后产生error。
@Test
public void testStepVerifier() {
Flux a = Flux.just(1, 2, 3, 4).concatWith(Mono.error(new RuntimeException("err")));
// 使用create方法创建
StepVerifier.create(a)
.expectNext(1)
.expectNext(2)
// 支持一次检查多个value
.expectNext(3, 4)
.expectError(RuntimeException.class)
.verify();
}
期望流正常结束
Flux a = Flux.just(1, 2, 3, 4);
StepVerifier.create(a)
.expectNext(1, 2, 3, 4)
.expectComplete()
.verify();
判断元素是否符合一些特性
Flux a = Flux.just("a", "aa", "a2323");
StepVerifier.create(a)
.expectNextMatches(i -> ((String) i).startsWith("a"))
.expectNextMatches(i -> ((String) i).startsWith("a"))
.expectNextMatches(i -> ((String) i).startsWith("a"))
.expectComplete()
.verify();
如果流的元素很多,逐个expectNext()显然不合适;使用thenConsumeWhile()替代:
int max = 1000;
Flux a = Flux.range(1, max);
StepVerifier.create(a)
.thenConsumeWhile(o -> ((Integer) o) <= max)
.expectComplete()
.verify();
处理时间问题
流的数据是动态的,可能间隔一段时间才到来,怎么加快单元测试的执行速度?
StepVerifier使用VirtualTimeScheduler来解决上面问题:
Prepare a new StepVerifier in a controlled environment using
VirtualTimeSchedulerto manipulate a virtual clock viaStepVerifier.Step.thenAwait.The scheduler is injected into all
Schedulersfactories, which means that any operator created within the lambda without a specific scheduler will use virtual time.
StepVerifier.withVirtualTime(() -> Flux.range(1, 10).delayElements(Duration.ofMinutes(1)))
// 触发订阅
.expectSubscription()
// 触发时间飞逝
.thenAwait(Duration.ofSeconds(30))
.expectNextCount(0)
.thenAwait(Duration.ofSeconds(10))
// 期望一段时间内没有事件
.expectNoEvent(Duration.ofSeconds(10))
.thenAwait(Duration.ofMinutes(100))
.expectNextCount(10)
.expectComplete()
.verify();