I am using MockMvc to test a controller. The controller has an ObjectMapper and HttpServletRequest as arguments. I instantiate the controller in my test class with these arguments. When I use MockMvc to make the request, the Name @RequestParam is successfully passed to the controller. However outside of this, the request is null. The accept header is set on the MockMvc request as:
mockMvc.perform(get("/birthday-cards?name=Jack").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print());
when the request is accessed in the controller, the request header is null.
String accept = request.getHeader("Accept");
I believe this is because once I get into the controller method body, the request is using the MockHttpServletRequest created when initializing the Controller in the test class.
The full code of the controller:
@Controller
public class HappyBirthdayApiController implements HappyBirthdayApi {
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@Autowired
public HappyBirthdayController(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
@Override
public Optional<ObjectMapper> getObjectMapper() {
return Optional.ofNullable(objectMapper);
}
@Override
public Optional<HttpServletRequest> getRequest() {
return Optional.ofNullable(request);
}
@Override
public ResponseEntity<String> getHappyBirthday(@ApiParam(value = "Filter by name") @Valid @RequestParam(value = "name", required = false) String name) {
//Request is null!
String accept = request.getHeader("Accept");
if (accept == null || !accept.equals(MediaType.APPLICATION_JSON_VALUE))
throw new UnsupportedMediaTypeException("Accept header must be " + MediaType.APPLICATION_JSON_VALUE);
);
String message = "Happy Birthday " + name;
return new ResponseEntity<>(message, HttpStatus.OK);
}
}
The test class:
public class BirthdayCardsApiControllerTest{
private MockMvc mockMvc;
private final MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
@InjectMocks
private BirthdayCardsApiController controller;
@Before
public void setUp(){
controller = new BirthdayCardsApiController(new ObjectMapper(), mockHttpServletRequest);
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void getHappyBirthdayTest() throws Exception{
mockMvc.perform(get("/birthday-cards?name=Jack").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print());
}
}
Is there a way to share the same HttpServletRequest used by MockMvc and when instantiating the controller under test?
HttpServletRequestto me. Your controller constructor should not take in theHttpServletRequest, instead it should be your API methodgetHappyBirthdaythat accepts it.