使用 Mockito 测试 Mono 和 Flux

Testing Mono and Flux using Mockito

我目前正在为我的 REST 端点编写一些基本的单元测试。为此,我使用 Mockito。举个例子:

@MockBean
private MyService service;

@Test
public void getItems() {
    Flux<Item> result = Flux.create(sink -> {
        sink.next(new Item("1"));
        sink.next(new Item("2"));
        sink.complete();
    });

    Mono<ItemParams> params = Mono.just(new ItemParams("1"));

    Mockito.when(this.service.getItems(params)).thenReturn(result);

    this.webClient.post().uri("/items")
            .accept(MediaType.APPLICATION_STREAM_JSON)
            .contentType(MediaType.APPLICATION_STREAM_JSON)
            .body(BodyInserters.fromPublisher(params, ItemParams.class))
            .exchange()
            .expectStatus().isOk()
            .expectBodyList(Item.class).isEqualTo(Objects.requireNonNull(result.collectList().block()));
}

此实现会导致以下错误:

java.lang.AssertionError: Response body expected:<[Item(name=1), Item(name=2)]> but was:<[]>

> POST /items
> WebTestClient-Request-Id: [1]
> Accept: [application/stream+json]
> Content-Type: [application/stream+json]

Content not available yet

< 200 OK
< Content-Type: [application/stream+json;charset=UTF-8]

No content

当我将 Mockito 语句中的参数与 Mockito.any()

交换时
Mockito.when(this.service.getItems(Mockito.any())).thenReturn(result);

测试顺利通过。 这意味着由于某种原因,我放入 Mockito 语句的 params 不等于我放入 BodyInserters.fromPublisher(params, ItemParams.class)

params 对象

那我应该如何测试我的功能?

编辑

REST 端点

@PostMapping(path = "/items", consumes = MediaType.APPLICATION_STREAM_JSON_VALUE, produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<Item> getItems(@Valid @RequestBody Mono<ItemParams> itemParms) {
    return this.service.getItems(itemParms);
}

实际对象 @RequestBody Mono<ItemParams> itemParms 会不会与您创建并通过测试的对象不同?

您可以利用 thenAnswer 来验证实际传递给服务的对象的内容:

Mockito.when(this.service.getItems(Mockito.any()))
       .thenAnswer(new Answer<Flux<Item>>() {

    @Override
    public Flux<Item> answer(InvocationOnMock invocation) throws Throwable {
        Mono<ItemParams> mono = (Mono<ItemParams>)invocation.getArgument(0);

        if(/* verify that paseed mono contains new ItemParams("1")*/){
          return result;
        }

        return null;
    }
});