有请求时模拟 WebClient post body
Mocking a WebClient post when there's a request body
关于模拟 WebClient object,有几个问题和有用的答案。但是我在用 body 做 post 时仍然有问题。我只是在使用 Mockito 而不是 mockwebserver。
这是我正在测试的方法:
public class RestClient extends BaseRestClient {
...
public <T,G> Mono<T> post(String url, G req, Class<T> resp) throws IOException {
Mono<T> response = null;
response = this.getWebClient().post()
.uri(url)
.header(HttpHeaders.CONTENT_TYPE,JSON_CONTENT_TYPE)
.accept(MediaType.APPLICATION_JSON)
//.body(BodyInserters.fromObject(req))
.header(HttpHeaders.AUTHORIZATION, BEARER + token)
.retrieve()
.bodyToMono(resp).log();
return response.map(resp::cast);
}
...
注意注释掉的 body 行。
这是与上面的代码配合使用的测试 - 再次注意测试中注释掉的行:
@Mock
WebClient webClient;
@Mock
WebClient.RequestBodyUriSpec requestBodyUriSpec;
@Mock
WebClient.RequestHeadersSpec requestHeadersSpec;
@Mock
WebClient.RequestBodySpec requestBodySpec;
@Mock
WebClient.ResponseSpec responseSpec;
@InjectMocks
RestClient restClient;
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
//when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.retrieve()).thenReturn(responseSpec);
restClient.post("http://sampleurl",Object.class, Object.class);
}
同样,一切正常。但是,如果我将注释掉的行放回代码中,这意味着此 post 有一个 body,并通过将注释掉的行放回测试中来模拟 body,那么我在代码中 .retrieve() 上会得到 NullPointerException。就像我缺少一个 object 来模拟一样。
我什至为 requestHeadersSpec 和 requestBodyUriSpec:
嘲笑 .retrieve()
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec);
仍然没有成功。有什么想法吗?
如果您使用 @InjectMocks
,则无需创建 new RestClient()
。
此外,由于您正在嘲笑 WebClient
,因此您不需要嘲笑 WebClient.
*` .
所以代码变成
@Mock
WebClient webClient;
@InjectMocks
RestClient restClient;
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
//when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.retrieve()).thenReturn(responseSpec);
restClient.post("http://sampleurl",Object.class, Object.class);
}
我错过了模拟 requestHeadersSpec 的 "header" 方法:
when(requestHeadersSpec.header(any(),any())).thenReturn(requestHeadersSpec);
所以,这现在工作正常:
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestHeadersSpec.header(any(),any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
Assert.assertNotNull(restClient.post("http://sampleurl",Object.class, Object.class));
}
在我的 WebClient 代码中添加 headers 之后它开始像魔术一样工作
@Test
public void postMethod() {
when(webClient.post()).thenReturn(requestBodyUriMock);
when(requestBodyUriMock.uri(anyString())).thenReturn(requestBodyMock);
when(requestBodyMock.header(any(),any())).thenReturn(requestBodyMock);
when(requestHeadersMock.header(any(),any())).thenReturn(requestHeadersMock);
when(requestBodyMock.accept(any())).thenReturn(requestBodyMock);
when(requestBodyMock.contentType(any())).thenReturn(requestBodyMock);
when(requestBodyMock.body(any())).thenReturn(requestHeadersMock);
when(requestHeadersMock.retrieve()).thenReturn(responseMock);
when(responseSpec.bodyToMono(String.class))
.thenReturn(Mono.just("output"));
//WebClient call
TestResponse test = service.testMethod(mockObject);
assertEquals(test.Status(), 200);
}
模拟 webclient post 方法与 request-body
示例:-
List<ParamountRxPriceResponse> paramountRxPriceResponse = paramountRxWebClient.post()
.uri(paramountRxuri.toString()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON).bodyValue(paramountRxPriceRequest).retrieve()
.bodyToMono(new ParameterizedTypeReference<List<ParamountRxPriceResponse>>() {
}).block();
模拟的测试用例。
@Test
public void testSbuildBaseBPricingFormat() {
when(webClientMock.post()).thenReturn(requestBodyUriMock);
when(requestBodyUriMock.uri(Mockito.anyString())).thenReturn(requestBodyMock);
when(requestBodyMock.contentType(Mockito.any())).thenReturn(requestBodyMock);
when(requestBodyMock.accept(Mockito.any())).thenReturn(requestBodyMock);
when(requestBodyMock.bodyValue(ArgumentMatchers.any())).thenReturn(requestHeadersMock);
when(requestHeadersMock.retrieve()).thenReturn(responseMock);
when(responseMock.bodyToMono(ArgumentMatchers.<ParameterizedTypeReference<List<ParamountRxPriceResponse>>>any())).thenReturn(Mono.just(getParamountRxPriceResponse()));
CompletableFuture<PricingResponse> actulaResultResponse = paramountRxResponseBuilderService
.buildBasePricingFormat(webClientMock,ProductInfoRequest.builder().formulationId("32332332332").quantity("10").zipCode("423894").build() ,"https://testUri.com","2323321");
assertNotNull(actulaResultResponse);
}
关于模拟 WebClient object,有几个问题和有用的答案。但是我在用 body 做 post 时仍然有问题。我只是在使用 Mockito 而不是 mockwebserver。
这是我正在测试的方法:
public class RestClient extends BaseRestClient {
...
public <T,G> Mono<T> post(String url, G req, Class<T> resp) throws IOException {
Mono<T> response = null;
response = this.getWebClient().post()
.uri(url)
.header(HttpHeaders.CONTENT_TYPE,JSON_CONTENT_TYPE)
.accept(MediaType.APPLICATION_JSON)
//.body(BodyInserters.fromObject(req))
.header(HttpHeaders.AUTHORIZATION, BEARER + token)
.retrieve()
.bodyToMono(resp).log();
return response.map(resp::cast);
}
...
注意注释掉的 body 行。
这是与上面的代码配合使用的测试 - 再次注意测试中注释掉的行:
@Mock
WebClient webClient;
@Mock
WebClient.RequestBodyUriSpec requestBodyUriSpec;
@Mock
WebClient.RequestHeadersSpec requestHeadersSpec;
@Mock
WebClient.RequestBodySpec requestBodySpec;
@Mock
WebClient.ResponseSpec responseSpec;
@InjectMocks
RestClient restClient;
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
//when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.retrieve()).thenReturn(responseSpec);
restClient.post("http://sampleurl",Object.class, Object.class);
}
同样,一切正常。但是,如果我将注释掉的行放回代码中,这意味着此 post 有一个 body,并通过将注释掉的行放回测试中来模拟 body,那么我在代码中 .retrieve() 上会得到 NullPointerException。就像我缺少一个 object 来模拟一样。
我什至为 requestHeadersSpec 和 requestBodyUriSpec:
嘲笑 .retrieve()when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec);
仍然没有成功。有什么想法吗?
如果您使用 @InjectMocks
,则无需创建 new RestClient()
。
此外,由于您正在嘲笑 WebClient
,因此您不需要嘲笑 WebClient.
*` .
所以代码变成
@Mock
WebClient webClient;
@InjectMocks
RestClient restClient;
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
//when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.retrieve()).thenReturn(responseSpec);
restClient.post("http://sampleurl",Object.class, Object.class);
}
我错过了模拟 requestHeadersSpec 的 "header" 方法:
when(requestHeadersSpec.header(any(),any())).thenReturn(requestHeadersSpec);
所以,这现在工作正常:
@Test
public void postTest() throws IOException {
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodySpec);
when(requestBodySpec.header(any(),any())).thenReturn(requestBodySpec);
when(requestHeadersSpec.header(any(),any())).thenReturn(requestHeadersSpec);
when(requestBodySpec.accept(any())).thenReturn(requestBodySpec);
when(requestBodySpec.body(any())).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(ArgumentMatchers.<Class<String>>notNull()))
.thenReturn(Mono.just("resp"));
Assert.assertNotNull(restClient.post("http://sampleurl",Object.class, Object.class));
}
在我的 WebClient 代码中添加 headers 之后它开始像魔术一样工作
@Test
public void postMethod() {
when(webClient.post()).thenReturn(requestBodyUriMock);
when(requestBodyUriMock.uri(anyString())).thenReturn(requestBodyMock);
when(requestBodyMock.header(any(),any())).thenReturn(requestBodyMock);
when(requestHeadersMock.header(any(),any())).thenReturn(requestHeadersMock);
when(requestBodyMock.accept(any())).thenReturn(requestBodyMock);
when(requestBodyMock.contentType(any())).thenReturn(requestBodyMock);
when(requestBodyMock.body(any())).thenReturn(requestHeadersMock);
when(requestHeadersMock.retrieve()).thenReturn(responseMock);
when(responseSpec.bodyToMono(String.class))
.thenReturn(Mono.just("output"));
//WebClient call
TestResponse test = service.testMethod(mockObject);
assertEquals(test.Status(), 200);
}
模拟 webclient post 方法与 request-body
示例:-
List<ParamountRxPriceResponse> paramountRxPriceResponse = paramountRxWebClient.post()
.uri(paramountRxuri.toString()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON).bodyValue(paramountRxPriceRequest).retrieve()
.bodyToMono(new ParameterizedTypeReference<List<ParamountRxPriceResponse>>() {
}).block();
模拟的测试用例。
@Test
public void testSbuildBaseBPricingFormat() {
when(webClientMock.post()).thenReturn(requestBodyUriMock);
when(requestBodyUriMock.uri(Mockito.anyString())).thenReturn(requestBodyMock);
when(requestBodyMock.contentType(Mockito.any())).thenReturn(requestBodyMock);
when(requestBodyMock.accept(Mockito.any())).thenReturn(requestBodyMock);
when(requestBodyMock.bodyValue(ArgumentMatchers.any())).thenReturn(requestHeadersMock);
when(requestHeadersMock.retrieve()).thenReturn(responseMock);
when(responseMock.bodyToMono(ArgumentMatchers.<ParameterizedTypeReference<List<ParamountRxPriceResponse>>>any())).thenReturn(Mono.just(getParamountRxPriceResponse()));
CompletableFuture<PricingResponse> actulaResultResponse = paramountRxResponseBuilderService
.buildBasePricingFormat(webClientMock,ProductInfoRequest.builder().formulationId("32332332332").quantity("10").zipCode("423894").build() ,"https://testUri.com","2323321");
assertNotNull(actulaResultResponse);
}