Having a problem with my mocked return response from my controller.
The async response is returning as the actual POJO not the serialized json.
Running the application and using Postman, the returned response is indeed a JSON Object... but testing it returns the actual mock POJO I've created... here is my test case.
@WebMvcTest(CustomerController.class)
class CustomerControllerTest {
@Autowired
MockMvc mvc;
@MockBean
private CustomerService customerService;
private Mono<OtcBalanceResponse> responseMono;
private OtcBalanceResponse otcResponseMock;
@BeforeEach
void setupMocks() {
OtcBalanceResponse otcResponseMock = new OtcBalanceResponse();
otcResponseMock.setOtcBalance(new BigDecimal("1.30"));
otcResponseMock.setUserId("testID");
responseMono = Mono.just(otcResponseMock);
}
@Test
void testGetCustomerOTCBalance() throws Exception {
when(customerService.getCustomerOTCBalance((OtcBalanceRequest) any()))
.thenReturn(responseMono);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/customer/otc-balance").accept(MediaType.APPLICATION_JSON);
mvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.jsonPath("$.otcBalance").value(1.30));
}
}
here is my Controller class
@GetMapping("/otc-balance")
public Mono<OtcBalanceResponse> getCustomerOTCBalance(OtcBalanceRequest otcBalanceRequest){
return customerService.getCustomerOTCBalance(otcBalanceRequest);
}
Here is my service
public Mono<OtcBalanceResponse> getCustomerOTCBalance(OtcBalanceRequest request) {
return webClientBuilder
.baseUrl(customerBase)
.build()
.post()
.uri(otcBalancePath)
.body(BodyInserters.fromValue(request))
.retrieve()
.bodyToMono(OtcBalanceResponse.class);
}
this is my logged result
Async:
Async started = true
Async result = OtcBalanceResponse(otcBalance=1.30, otcRolloverFlag=false, isIncommMember=false, otcStartDate=null, otcEndDate=null)
CodePudding user response:
As you are using Async coding (and not full webflux) you need to do that with MockMvc
as well. The javadoc of the MockMvcRequestBuilders
has an example of such a thing. Applying that to your code would make it something like this.
@Test
void testGetCustomerOTCBalance() throws Exception {
when(customerService.getCustomerOTCBalance((OtcBalanceRequest) any()))
.thenReturn(responseMono);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/customer/otc-balance").accept(MediaType.APPLICATION_JSON);
MvcResult result = mvc.perform(requestBuilder).andExpect(request().asyncStarted())
.andReturn();
mvc.perform(asyncDispatch(result))
.andExpect(MockMvcResultMatchers.jsonPath("$.otcBalance").value(1.30));
}
Something along those lines.
CodePudding user response:
You seem to be using webflux, the easiest path is to use webflux-specific classes:
- WebFluxTest instead of WebMvcTest
- WebTestClient instead of MockMvc
@WebFluxTest(CustomerController.class)
class CustomerControllerTest {
@Autowired
private WebTestClient webClient;
// ...
@Test
void testGetCustomerOTCBalance() throws Exception {
when(customerService.getCustomerOTCBalance(any()))
.thenReturn(responseMono);
webClient.get().uri("/customer/otc-balance")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.otcBalance").isEqualTo(1.30);
}
}
Other remarks - you are not OtcBalanceRequest
to the controller - but any()
argument matcher accepts null. Using a eq
argument matcher would make your test better - you would check that the request is correctly deserialized by the controller.