Project Reactor block() 与 StepVerifier 中的正确测试模式

pov*_*nko 5 testing unit-testing reactive-programming project-reactor

最近我注意到我的团队在如何在 Reactor 中编写测试时遵循两种方法。第一个是借助.block()方法。它看起来像这样:

@Test
void set_entity_version() {
    Entity entity = entityRepo.findById(ID)
                              .block();
    assertNotNull(entity);
    assertFalse(entity.isV2());

    entityService.setV2(ID)
                 .block();

    Entity entity = entityRepo.findById(ID)
                              .block();

    assertNotNull(entity);
    assertTrue(entity.isV2());
}
Run Code Online (Sandbox Code Playgroud)

第二个是关于使用StepVerifier. 它看起来像这样:

@Test
void set_entity_version() {

    StepVerifier.create(entityRepo.findById(ID))
                .assertNext(entity -> {
                    assertNotNull(entity);
                    assertFalse(entity.isV2());
                })
                .verifyComplete();
            
    StepVerifier.create(entityService.setV2(ID)
                                     .then(entityRepo.findById(ID)))
                .assertNext(entity -> {
                    assertNotNull(entity);
                    assertTrue(entity.isV2());
                })
                .verifyComplete();
}
Run Code Online (Sandbox Code Playgroud)

以我的拙见,第二种方法看起来更具反应性。此外,官方文档对此也说得很清楚:

StepVerifier 提供了一种声明性方式,通过表达对订阅时将发生的事件的期望,为异步发布者序列创建可验证脚本。

不过,我真的很好奇,应该鼓励使用什么方式作为在 Reactor 中进行测试的主要途径。该.block()方法应该完全放弃还是在某些情况下可能有用?如果是,那么此类案例是什么?

谢谢!

pov*_*nko 5

来自https://medium.com/swlh/stepverifier-vs-block-in-reactor-ca754b12846b

\n
\n

block()两种StepVerifier测试模式都有优点和缺点。因此,有必要定义一个模式或一组规则\n来指导我们如何使用 StepVerifier 和 block()。

\n

为了决定使用哪些模式,我们可以尝试回答\n以下问题,这些问题将为\n我们将要编写的测试提供明确的期望:

\n
    \n
  • 我们是在尝试测试代码的反应性方面还是只是测试代码的输出?
  • \n
  • 在哪种模式中,我们基于 3 A\xe2\x80\x99 测试(即排列、执行和断言)找到了清晰性,以便使测试\n易于理解?
  • \n
  • 在测试反应式代码时,block() API 相对于 StepVerifier 有何限制?在以下情况下,哪种 API 更适合编写测试\n Exception
  • \n
\n

如果您尝试回答上述所有问题,您将找到 \n\n\n\xe2\x80\x9cwhat\xe2\x80\x9d 和 \xe2\x80\x9cwhere\xe2\x80\x9d 的答案。因此,在阅读以下答案之前请先思考一下:

\n
    \n
  • block() 测试代码的输出而不是反应方面。在这种情况下,我们关心的是测试代码的输出,而不是代码的响应方面,我们可以使用 block() 而不是 StepVerifier,因为它易于编写,并且测试
    更具可读性。
  • \n
  • block() 模式的断言库在3 A\xe2\x80\x99s patternie ArrangeAct和方面Assert比 StepVerifier 更好地组织。在 StepVerfier 中,当测试模拟类的方法调用时,甚至在测试 Mono 输出时,必须以链式方法的形式编写期望,这与我认为的断言不同,断言会降低测试的可读性。另外,如果您忘记编写\n最终步骤,即verify()在 StepVerifier 的情况下,代码\n将不会被执行,并且测试将变为绿色。因此,开发人员在调用链末端的 verify 时必须非常小心。
  • \n
  • 反应式代码的某些方面无法使用 block() API 进行测试。在这种情况下,当我们测试一系列Flux数据或订阅延迟或订阅Schedulers等时,开发人员必须使用 StepVerifier,则应使用 StepVerifier。
  • \n
  • 要使用 block() API 验证异常,您需要使用assertThatThrownBy 断言库中捕获异常的 API。\n 通过使用断言 API,可以断言错误消息和异常实例。StepVerifier 还通过 API 提供异常断言expectError(),并支持
    在 Flux 元素中抛出错误之前对元素进行断言,这是 block() 无法实现的。因此,对于异常的断言,StepVerifier 比 block() 更好,因为它可以断言
    两者Mono/Flux
  • \n
\n
\n