Fluent api, enable testing of controller as controller
, not just as a method (think request mapping).
See the full presentation from springsource here.
Get the sample codes (NOT for the springsource presentation) here.
I would say this is a unit test because we will mock the collborators
, although we also have the option to not mock the collaborators
thus doing something like an integration test.
In the spirit of unit-testing, I personally prefer to do standalone testing on the controller, by mocking the collaborators
and testing one controller at a time.
It will handle the creation of DispatcherServlet
runtime for the test, so we can also test the mvc wiring, not just the inner workings of the methods.
We won't call the controller methods directly. Instead we will create a mock request and pass it to the provided mvc test infrastructure.
Classes in org.springframework.test.web.servlet.*
Check for yourself here.
We have several options for asserting, either manually asserting the response
result and/or the ModelAndView
object, or using the springframework api.
For asserting the result manually, I would prefer asserting the ModelAndView
, instead of the response
result.
I think asserting the response
result would only be realistic if our controllers are json/xml web service endpoints. I don't feel like asserting html markup...
Asserting the response
result is also not supported if the rendering technology is jsp
(not running in a servlet container). Freemarker, Velocity, Xslt, etc, is supported. Another reason not to use jsp
?
Api that looks like a builder
pattern.
Creating Standalone Unit Test
...
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
...
@InjectMocks
private HomeController homeController;
...
@Mock
private TimeService timeService;
...
@Before
public void before() {
...
this.mockMvc = standaloneSetup(this.homeController).build();
}
...
Fluent Api
...
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
...
@Test
public void homeTest() throws Exception {
// note: we don't call the controller method manually here!
this.mockMvc.perform(get(HomeControllerTest.PATH)).andExpect(
status().isOk());
...
}
...
Access to underlying request, response, ModelAndView object
...
import static org.springframework.test.web.ModelAndViewAssert.assertModelAttributeValue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
...
@Test
public void homeAssertMavTest() throws Exception {
// note: we don't call the controller method manually here!
MvcResult mvcResult = this.mockMvc.perform(get(HomeControllerTest.PATH)).andReturn();
...
ModelAndView modelAndView = mvcResult.getModelAndView();
MockHttpServletRequest request = mvcResult.getRequest();
MockHttpServletResponse response = mvcResult.getResponse();
...
// assertions
...
// spring mvc ModelAndView specific assertion
assertModelAttributeValue(modelAndView, HomeControllerTest.SERVER_TIME,
HomeControllerTest.EN_RESULT);
...
}
...