I am writing a unit for a controller with spting boot @WebMvcTest
.
Using @WebMvcTest
, I will be able to inject a MockMvc
object as given below :-
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {TestConfig.class})
@WebMvcTest
class MyControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void my_controller_test() throws Exception {
mockMvc.perform(post("/create-user"))
.andExpect(status().isCreated());
}
}
In the controller I am injecting a Principal
argument using spring HandlerMethodArgumentResolver
. Please inform me how can I write a unit test with MockMvc
, so that I can inject a mock Principal
object as the argument in the controller method.
The sction Auto-configured Spring MVC tests explains that the Test annotated with @WebMvcTest
will scan beans of HandlerMethodArgumentResolver
. So I created a bean which extends HandlerMethodArgumentResolver
and return the mock Principal
object as below .
@Component
public class MockPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(Principal.class);
}
@Override
public Object resolveArgument(MethodParameter parameter...) throws Exception {
return new MockPrincipal();
}
}
But still the Argument MockPrincipal
is not getting passed to controller method.
Spring boot version :- 1.4.5.RELEASE
You are using MockMvc
to call your controller. With that you have to prepare the request with things like parameters, body, URL and also the principal. What you don't specify won't be included (you are now basically doing a call without an authenticated principal).
The Spring MVC Testing support for MockMvc is documented, in general, in the reference guide.
For more detailed info check the component that is used for building a mock request the MockHttpServletRequestBuilder
. Which is what your post
method will return, which should be a call the MockHttpServletRequestBuilders.post
(and probably a static import in your code). A [CTRL]+[SPACE] (or whatever your favorite code completion short cut is in your iDE) after post()
will give you some insight in what is available.
@Test
public void my_controller_test() throws Exception {
mockMvc.perform(post("/create-user").principal(new MockPrincipal())
.andExpect(status().isCreated());
}
Something like the above should do the trick.