0

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?

3
  • 1
    This seems like the wrong usage of HttpServletRequest to me. Your controller constructor should not take in the HttpServletRequest, instead it should be your API method getHappyBirthday that accepts it. Commented Aug 18, 2022 at 21:14
  • The classes were generated with swagger-codegen and that is how the classes were generated. Why do you think that is the wrong usage? Commented Aug 19, 2022 at 15:37
  • Did some digging, and not really a wrong usage of it link to other post. I suppose it's just a way I was not familiar with, the more you know. Commented Aug 19, 2022 at 16:37

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.