junit Webflux单元测试:调用不会进入.map和.flatMap

htzpubme  于 2023-06-29  发布在  其他
关注(0)|答案(1)|浏览(278)

我正在为webflux中的函数计算编写单元测试

@Override
    public Mono<SearchSessionAndETAResponse> calculate(DTO sessionRequest) throws ExecutionException, InterruptedException {
        List<GeospatialData> dataFromRedis =  getDataFromRedis(sessionRequest.getSessionId());
        return Mono.just(dataFromRedis)
                .map(data -> {
                    System.out.println("data::"+data);
                    return "entityIdentifiers";
                })
                .flatMap(entityIdentifiers -> {
                    System.out.println("entityIdentifiers::"+entityIdentifiers);
                    return etaService.entitiesEta("entityIdentifiers");
                })
                .map(wayPointRoute -> {
                    return searchSessionAndETAResponse;
                });
    }

下面是测试用例

@ExtendWith(MockitoExtension.class)
public class BroadCastingServiceImplTest {

    @InjectMocks
    private BroadCastingServiceImpl broadCastingService;
    @Mock
    private EtaService etaService;

   @BeforeEach
    void setUp() {
        closeable = MockitoAnnotations.openMocks(this);
    }

    @AfterEach
    void tearDown() throws Exception {
        closeable.close();
    }

@Test
    @DisplayName("Given a valid request, when SearchSession and calculate eta is called, it should search Broadcasting session and return eta")
    void givenValidRequest_whenSearchSessionAndCalculateEta_shouldReturnBroadCastingResponseDTO() throws ExecutionException, InterruptedException, IOException {
        // GIVEN
        UUID sessionId = UUID.randomUUID();
        DTO searchSessionAndCalculateETA = new DTO();
        searchSessionAndCalculateETA.setSessionId(sessionId.toString());
        searchSessionAndCalculateETA.setWaypoints(List.of("waypointsDTO", "waypointsDTO2"));
        given(etaService.entitiesEta("entitiesEtaRequestDTO")).willReturn(Mono.just(List.of("entitiesEtaResponseDTO")));

        // WHEN
        Mono<SearchSessionAndETAResponse> result = broadCastingService.searchSessionAndCalculateETA(searchSessionAndCalculateETA);
    }
}

问题:
当我运行测试用例时,即使dataFromRedis不为null,调用也不会进入.map,.flatMap和.map。有什么我错过了吗?

wgx48brx

wgx48brx1#

在您的测试中,您只是创建了Mono,但并没有真正“运行”它,更确切地说,您并没有订阅它。
使用React式代码有两个阶段:
1.首先,您编写React流的规范,它告诉要做什么,但不启动进程。Mono只是一个复杂的内存结构,有很多lambda函数告诉我们什么时候做什么。
1.然后你订阅Mono--只有这样才能启动整个过程,并开始调用所有的lambda表达式。只有这样,“调用将进入.map和.flatMap”来解释你的话:)
阅读一些教程,例如。这个Baeldung的Intro To Reactor Core
如果你只是在简单的Spring应用程序中使用Mono来处理REST端点,你可能很容易错过这一点,因为你的@RestController只返回Mono,其余的(pun intended)由Spring处理。Spring订阅从控制器方法返回的Mono,并处理通过HTTP将结果传递给调用的。
单元测试中,你可以非常简单地调用它的block()方法,或者更恰当地使用StepVerifier

result.as(StepVerifier::create)
    .expectNext(objectToExpect)
    .verifyComplete();

只使用block()方法更像是一种变通方法。StepVerifier是对React式代码进行单元测试的正确方法。
注意不要只使用subscribe()方法,因为测试可能在订阅有时间执行之前就完成了,您将得到不可预测的结果。

相关问题