Spring WebFlux 程序测试

1、使用StepVerifier测试响应式流

        由于响应式框架不同于常规框架,测试复杂度相对困难。出于测试目的,Reactor 提供了额外的 reactor-test 模块,该模块提供了 StepVerifier。StepVerifier 提供了一个流式 API,用于为任何 Publisher 构建验证流程。

1.1、StepVerifier 要点

        验证 Publisher 主要有两种方法。第一种是 StepVerifier.<T>create(Publisher<T> source)。使用此技术构建的测试如下所示:

@Test
public void test1() {
    StepVerifier
        .create(Flux.just("bar", "foo"))
        //声明发出的事件:当前为订阅事件
        .expectSubscription()
        //声明订阅收到的第一个元素
        .expectNext("foo")
        //第二个元素
        .expectNext("bar")
        //声明当前流信号终止完成
        .expectComplete()
        .log()
        //对上述声明进行验证
        .verify();
}

        在此示例中,Publisher 应生成两个特定元素,后续操作将验证特定元素是否已传递给最终订阅者。该类提供的构建器技术可以定义验证过程中事件发生的顺序。根据前面的代码,第一个发出的事件必须是与订阅相关的事件,紧跟其后的事件必须是 foo 和 bar 字符串。最后, StepVerifier#expectCompletion 定义终止信号的存在。

        在此例中,必须是 Subscriber#onComplete 的调用,或者成功完成给定的 Flux。要执行验证,或者说对创建流进行订阅,就必须调用 .verify() 方法。verify() 是一个阻塞调用,它阻塞执行,直到流发出所有预期的事件。

        通过使用这种简单的技术,可以使用可计数的元素和事件来验证 Publisher。但是,用大量元素来验证流程是很困难的。如果检查的是该发布者已发出元素是否达到特定数量,可以使用 .expectNextCount() 。如下代码:

@Test
public void test2() {
    StepVerifier
        //创建一个响应式序列
        .create(Flux.range(0, 100))
        //声明处理的是订阅事件
        .expectSubscription()
        //期望下一个元素与指定的元素符合
        .expectNext(0)
        //声明从上一个元素开始,期望收到指定个数的元素
        .expectNextCount(98)
        //期望收到的下一个元素与指定的元素符合
        .expectNext(99)
        //期望收到完成信号
        .expectComplete()
        //执行阻塞验证
        .verify();
}

        尽管 .expectNextCount() 方法解决了一部分问题,但在某些情况下,仅仅检查发出元素的数量是不够的。例如,在验证负责按特定规则过滤或选择元素的代码时,检查所有发出的项是否与过滤规则匹配非常重要。为此,StepVerifier 可以使用 Java Hamcrest 等工具立即记录发出的数据及其验证。如下代码:

package cn.blnp.net.reactboot;

import cn.blnp.net.reactboot.entity.BookEntity;
import org.junit.jupiter.api.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.ArrayList;

/**
 * <p></p>
 *
 * @author lyb [email protected]
 * @version 1.0
 * @since 2025/1/16 9:51
 */
public class DemoTest {

    @Test
    public void test3() {
        //模拟接口查询取得数据
        Publisher<BookEntity> books = findAllBooks();

        //验证测试当前流结果
        StepVerifier
                .create(books)
                .expectSubscription()
                .recordWith(ArrayList::new)
                .expectNextCount(1)
                .consumeRecordedWith(book -> assertThat(
                        //待判定对象
                        book,
                        //比对规则
                        everyItem(
                                //判定传入对象是否有指定名字的属性
                                hasProperty("title",
                                        //当上述判定有指定属性时,则验证属性值是否与给定的一致
                                        equalTo("The Martian"))
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值