使用 Mockito 测试 Mono 和 Flux

Mul*_*ard 7 java unit-testing mocking mockito spring-webflux

我目前正在为我的 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()));
}
Run Code Online (Sandbox Code Playgroud)

此实现会导致以下错误:

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
Run Code Online (Sandbox Code Playgroud)

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

Mockito.when(this.service.getItems(Mockito.any())).thenReturn(result);
Run Code Online (Sandbox Code Playgroud)

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

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

编辑

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);
}
Run Code Online (Sandbox Code Playgroud)

Mac*_*ski 5

实际的对象 是否与@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;
    }
});
Run Code Online (Sandbox Code Playgroud)