reactor3提供了对应的测试包,maven最新版本如下:
1 2 3 4 5 6 |
<dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <version>3.4.13</version> <scope>test</scope> </dependency> |
reactor的test包,为我们提供了各种之前我们用到的Publisher的assert验证。其中核心的一个类就是StepVerifier。如果有任何不符合的情况,就会产生AssertionError报错。
最简单的就是可以直接调用StepVerifier的静态方法create来生成一个验证实例。我们最后验证的时候一定要调用verifyxxx()方法来产生最终的验证,不然StepVerifier是没有办法自己验证的。
这个验证工具提供的验证方法还是很多的,这里只简单介绍几种,详细的还是可以通过sdk的api来自己体验。
基础功能
最基础的一个使用方式上面也说了,就是通过静态方法来生成一个实例。如果用过mockito来写测试用例的话,会对这些用法很熟悉,下面先看一个最简单的例子。
1 2 |
Flux<String> flux = Flux.just("a", "b", "c"); StepVerifier.create(flux).expectNext("a", "b", "c").verifyComplete(); |
这就是一个简单的测试用例。我们先创建了一个产生字符串a、b、c的一个Flux,通过StepVerifier的create静态方法产生一个对应的实例,这时候调用expectNext方法,填入我们期望的返回内容,当然也就是a、b、c了,最后verifyComplete是说我们最后还期待有一个complete事件。
实际看下expectNext的api,他提供了一些重载的方法,可以接收任意参数长度,也可以传入一个数组。
我们flux最后是产生的complete事件,如果flux的实际方法在返回内容后抛出了一个异常,我们也可以最后来个verifyError(Class),来预期要产生的是哪种异常。
expectXXX的方法也还有别的,比如expectNextCount,就是说我们期望产生数据的长度,像上述的示例,其实就是3个。
结合Assertions
这里的Assertions,是org.assertj.core.api.Assertions,其实本身reactor-test里面也有一个,但是只是StepVerifier内部的接口。
下面直接看下StepVerifier与org.assertj.core.api.Assertions的结合使用示例:
首先有一个User的类,我这里简单写了就只有个age参数(这里用到了lombok)。
1 2 3 4 5 |
@AllArgsConstructor @Data class User { private int age; } |
接下来是测试内容:
1 2 3 |
StepVerifier.create(Flux.just(new User(1))) .assertNext(u -> Assertions.assertThat(u.getAge()).isEqualTo(1)) .verifyComplete(); |
可以看到,这里主要调用了一个assertNext的方法,最后同样我们期望是能够正常完结的,所以用的verifyComplete。
看中间这边,直接Assertions.assertThat获取对应user的age数据,通过isEqualTo来确认我们期望的内容。
时间魔法
最后再介绍一个神奇的功能,我们有一些需要做延时测试的功能,不可能真的去测试一个功能等那么久时间让方法去跑,所以我们可以调用对应的方法让时间快速过去。
还是看一个示例:
1 2 3 4 5 6 7 |
StepVerifier.withVirtualTime(() -> Flux.interval(Duration.ofSeconds(1)).take(3600)) .expectSubscription() .expectNoEvent(Duration.ofSeconds(1)) .thenAwait(Duration.ofSeconds(3599)) .expectNextCount(3600) .expectComplete() .verify(); |
实际上reactor为我们提供了虚拟时间的处理(内部结合Scheduler实现),这里我通过interval来实现一个1秒钟发射一个元素的序列(从0开始依次递增),然后task方法限制获取3600个,实际上也就是会持续产生一个小时。
固定写法,我们需要跟expectSubscription方法,然后有两个时间快进时间的方法,一个是expectNoEvent,事件继续进行给定时间,但是这段时间之中不能存在事件,另外一个thenAwait没什么说的就是快进时间。
其他的验证就都没什么区别了,我们期望元素数是3600个,然后触发complete事件。
这里有个坑,就是withVirtualTime方法的参数是一个Supplier(Supplier<? extends Publisher<? extends T>>),而这个Flux(或者Mono)产生的实例必须写在方法里面,如果你再外面生成一个Flux实例(Flux flux = Flux.interval(Duration.ofSeconds(1)).take(3600)),然后传进去变量的话是无法生效的。
这里我们也可以测试比如thenAwait给1秒,然后expectNext(0),再1秒,expectNext(1),都是可以的,有很多验证的方法,更多详细的用法可以通过api查看。
©原创文章,转载请注明来源: 赵伊凡's Blog
©本文链接地址: 响应式编程的测试StepVerifier