To have fast tests for my controller I want to use @WebMvcTest
. I wrote server-side unit tests for the controller (See DemoControllerTests
in the demo project). These are basically simple unit tests involving the sliced Spring application context:
@WebMvcTest(DemoController.class)
class DemoControllerTests {
@Autowired
private MockMvc mockMvc;
@Test
@WithAnonymousUser
void shouldNotHaveAccessWhenAnonymous() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(username = "pascal", roles = "USER")
void shouldHaveAccessWithUserRole() throws Exception {
this.mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello"));
}
}
But as soon as is start involving more dependencies in my WebSecurityConfig
like the MyUserDetailsService
(which itself has a dependency on the UserObjectRepository
) the problems start to appear.
@Autowired
public WebSecurityConfig(final MyUserDetailsService myUserDetailsService) {
this.myUserDetailsService = myUserDetailsService;
}
When I run the tests Spring cannot load the ApplicationContext (NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.MyUserDetailsService' available
).
This does make sense when I take a look at the documentation of @WebMvcTest
. It says that components, services, and repositories will not be auto-configured. But in the last section, it says that Spring Security will be auto-configured when using this annotation. Additional configuration is available using the @AutoConfigureMockMvc
.
From my point of view there nothing special to do and even though I want to set the secure
config in @AutoConfigureMockMvc
it is enabled by default and deprecated. They mention that the secure
property is deprecated since 2.1.0 in favor of Spring Security's testing support. But I cannot find more details about a dedicated Spring Security testing support regarding this topic (i already use @WithMockUser
etc. in my tests)
* <p>
* Using this annotation will disable full auto-configuration and instead apply only
* configuration relevant to MVC tests (i.e. {@code @Controller},
* {@code @ControllerAdvice}, {@code @JsonComponent},
* {@code Converter}/{@code GenericConverter}, {@code Filter}, {@code WebMvcConfigurer}
* and {@code HandlerMethodArgumentResolver} beans but not {@code @Component},
* {@code @Service} or {@code @Repository} beans).
* <p>
* By default, tests annotated with {@code @WebMvcTest} will also auto-configure Spring
* Security and {@link MockMvc} (include support for HtmlUnit WebClient and Selenium
* WebDriver). For more fine-grained control of MockMVC the
* {@link AutoConfigureMockMvc @AutoConfigureMockMvc} annotation can be used.
* <p>
The tests are fine in general. They test the controller methods and their method security configuration. The problems only start to roll in when I add more dependencies and separate classes which I then try to inject in my WebSecurityConfig
.
How can I mock these dependencies so that my controller tests are working with a sliced context instead of starting the whole application context with @SpringBootTest
?
Here is the demo project that shows the problem: https://github.com/pas2al/spring-playground
Aucun commentaire:
Enregistrer un commentaire