Use case:
say for instance i'm using mocking frameworks such as PowerMock, EasyMock and I have components within my controller that accept HttpServletRequest as an argument. Most of these frameworks rely on ArgumentMatchers that invoke the equals() methods to compare expected arguments versus actual ones. In the case of Mockmvc a new instance of MockHttpServletRequest is always created because it accepts a builder, so the following tests will always fail. One option would be to use a broader matcher of course, but ideally if I could specify the MockHttpServletRequest object instance to use that would work better.
As far as I can tell there is no way I can specify the instance of MockHttpServletRequest instantiated when I perform a call using mockMvc such as:
mockMvc.perform(get("/myPath"));
because the perform method accepts a Builder.
I know that I can build the request myself (i.e)
Integer id = new Integer(1);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/myPath").param(Constants.ID, id.toString());
MockHttpServletRequest request = requestBuilder.buildRequest(wac.getServletContext());
and then pass that into the perform() method but still creates an object id mismatch which is problematic when you are using testing matcher frameworks and the object does not override the equals() method. Obivously I could use a broader matcher but ideally I'd rather not do that. I could get a hold of the request with a
Example source and test:
```java @Autowired private MyService myService;
@GetMapping(value = "/myPath") public ModelAndView getDetail(HttpServletRequest request) { myService.invokeSomeMethod(request); }
MyService myServiceMock = EasyMock.createMock(MyService.class); MockHttpServletRequest mockRequest = new MockHttpServletRequest();
EasyMock.reset(myService); myService.invokeSomeMethod(request); / this will always fail as MockHttpServletRequest does not override equals() so the default Object.equals() is used .. and the mockMvc.perform method creates its own instance of MockHttpServletRequest / EasyMock.expectLastCall(); EasyMock.replay(myService);
mockMvc.perform(get("/myPath").andExpect(status().is(HttpStatus.OK.value()));
EasyMock.verify(myService);`
I suppose I could dance around the problem using the RequestPostProcessor but that seems ugly.
**Comment From: rstoyanchev**
Perhaps this:
```java
MockHttpServletRequest request = get("/myPath").buildRequest(this.servletContext);
// EasyMock initializations...
mockMvc.perform(sc -> request)
.andExpect(status().is(HttpStatus.OK.value()));;
Or this:
RequestPostProcessor initializer = request -> {
// EasyMock initializations...
return request;
};
mockMvc.perform(get("/myPath").with(initializer))
.andExpect(status().is(HttpStatus.OK.value()));;
Obviously I could use a broader matcher but ideally I'd rather not do that.
Could you clarify why not? Is it because it forces all arguments to be broader or something else?
Comment From: JohnZ1385
@rstoyanchev thaks your first suggestion of
mockMvc.perform(sc -> request).andExpect(status().is(HttpStatus.OK.value()));;
does work. The functional programming slipped my mind here.
Also yes you are correct my initial concern here was the forcing of all arguments to be broader, generally with a lot of these frameworks use you use a broader matcher for one argument you are forced to for the remaining arguments in a mocked call. That may not matter so much for an object like a request I suppose but say for instance like a String .. there should never be a need for a broader matcher on an object like that. Anyways I can use this suggestion, thanks for your time.