I am trying to make intergration tests for my webflux controller, but the test are failing either on not set content-type or on empty content. Controller class:
@RestController
@RequiredArgsConstructor
@SecurityRequirement(name = "bearerAuth")
@Log4j2
public class OnboardingController {
private final Service service;
@GetMapping(value = "/organizationQuotas", produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<OrganizationQuota> getOrganizationQuotas() {
return service.getAllOrganizationQuotas();
}
}
Service class is a simple flux-returning service. Test class:
@WebMvcTest(OnboardingController.class)
@RunWith(SpringRunner.class)
public class OnboardingControllerIT {
@MockBean
Service service;
private EasyRandom easyRandom = new EasyRandom();
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(authorities = {"..."})
@DisplayName("Should List All organization quotas when GET request to /organizationQuotas")
public void shouldReturnOrganizationQuotas() throws Exception {
when(service.getAllOrganizationQuotas())
.thenReturn(Flux.fromStream(easyRandom.objects(OrganizationQuota.class, 5)));
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/organizationQuotas").accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
// .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.*", isA(ArrayList.class)))
.andReturn();
}
}
At this state the output looks like this:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /organizationQuotas
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json"]
Body = null
Session Attrs = {SPRING_SECURITY_CONTEXT=org.springframework.security.core.context.SecurityContextImpl@d1e9b4bb: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d1e9b4bb:...}
Handler:
Type = controller.OnboardingController
Method = controller.OnboardingController#getOrganizationQuotas()
Async:
Async started = true
Async result = [OrganizationQuota{allowPaidServicePlans=true, ...}]
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
and it ends with exception
No value at JSON path "$.*"
java.lang.AssertionError: No value at JSON path "$.*"
...
I have these dependencies
testImplementation 'org.jeasy:easy-random-randomizers:5.0.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testCompile 'io.projectreactor:reactor-test'
Security should work ok. I can see the async result that is correct but my matchers are not working with it. The content type is not returned as well. Is it because of the async character of request? How can I make it evaluate? Thanks for help.
I found it at howToDoInJava that testing async controller is different:
I had to use asyncDispatch
method. Form the referenced page, here is the example:
@Test
public void testHelloWorldController() throws Exception
{
MvcResult mvcResult = mockMvc.perform(get("/testCompletableFuture"))
.andExpect(request().asyncStarted())
.andDo(MockMvcResultHandlers.log())
.andReturn();
mockMvc.perform(asyncDispatch(mvcResult))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith("text/plain"))
.andExpect(content().string("Hello World !!"));
}
now it works correctly.