如何Mock接收实体类请求且需调用block()方法的WebClient?
我想要Mock一个接收实体类作为请求参数、且需要调用.block()方法将Mono转换为目标类的WebClient。需要Mock的调用代码如下:
response = webClientSample.post().uri(builder.toUriString()) .headers(httpHeader -> httpHeader.addAll(httpHeaders)) .body(BodyInserters.fromValue(SampleRequest)).retrieve().bodyToMono(SampleResponse.class).block();
当前Mock代码运行时,上述调用链的.body(...).retrieve().bodyToMono(...).block()部分抛出空指针异常。我尝试通过以下代码Mock block()方法(populateSampleResponse为返回SampleResponse实例的方法):
Mockito.when(Mono.just(populateSampleResponse()).block()).thenReturn(populateSampleResponse());
但触发报错:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
你不能直接Mock Mono.block(),因为Mono.just(...)返回的是真实Mono实例,并非Mockito生成的Mock对象,所以会触发方法调用错误。正确做法是按WebClient的调用链,逐步Mock每个环节的返回对象:
初始化WebClient Mock实例
确保webClientSample是Mock对象,可通过注解或手动初始化:WebClient webClientSample = Mockito.mock(WebClient.class); // 或使用@Mock注解配合MockitoAnnotations.openMocks(this)Mock post()方法的返回值
WebClient.RequestBodyUriSpec requestBodyUriSpec = Mockito.mock(WebClient.RequestBodyUriSpec.class); Mockito.when(webClientSample.post()).thenReturn(requestBodyUriSpec);Mock uri()方法的返回值
Mockito.when(requestBodyUriSpec.uri(Mockito.anyString())).thenReturn(requestBodyUriSpec);Mock headers()方法的返回值
Mockito.when(requestBodyUriSpec.headers(Mockito.any(Consumer.class))).thenReturn(requestBodyUriSpec);Mock body()方法的返回值
WebClient.RequestHeadersSpec requestHeadersSpec = Mockito.mock(WebClient.RequestHeadersSpec.class); // 匹配任意BodyInserter,也可根据需要精确匹配SampleRequest参数 Mockito.when(requestBodyUriSpec.body(Mockito.any(BodyInserter.class))).thenReturn(requestHeadersSpec);Mock retrieve()方法的返回值
WebClient.ResponseSpec responseSpec = Mockito.mock(WebClient.ResponseSpec.class); Mockito.when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);Mock bodyToMono()及block()方法
Mock一个Mono对象,让它的block()返回预期的SampleResponse实例:Mono<SampleResponse> mockMono = Mockito.mock(Mono.class); Mockito.when(responseSpec.bodyToMono(SampleResponse.class)).thenReturn(mockMono); Mockito.when(mockMono.block()).thenReturn(populateSampleResponse());
如果使用Spring Boot 2.3+,也可以考虑使用WebClientTest切片测试,它会自动配置WebClient的Mock环境,简化Mock代码。
内容的提问来源于stack exchange,提问作者cwf8951

