Reputation: 73
I currently have an app built with Spring Boot 2, Spring MVC, Spring Data/JPA and Thymeleaf.
I'm writing some unit/integration tests and I'd like to test the controller, which is secured by SpringSecurity backed by a database with registered users.
What would be the best approach here to test it? I've unsuccessfully tried a few of them like using annotations like @WithMockUser
.
Edit: Just a reminder that I'm not testing @RestController
s. I'm directly injecting a @Controller
on my test class and calling its methods. It works just fine without Spring Security.
One example:
@Controller
public class SecuredController {
@GetMapping("/")
public String index() {
return "index";
}
}
The /
path is secured by Spring Security and would normally redirect to /login
to authenticate the user.
My unit test would look like this:
@WebMvcTest(controllers = SecuredController.class)
class SecuredControllerTest {
@Autowired
private SecuredController controller;
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(username = "user", password = "pass", roles = {"USER"})
public void testAuthenticatedIndex() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andDo(print());
}
}
The first errors I get is that is asks me to inject my UserDetailsService implementation, which is something that I'd like to avoid. But if I do inject the service, the test works, but returns 404 instead of 200.
Any ideas?
Upvotes: 1
Views: 2123
Reputation: 1564
You will need to add your security configurations to the Spring context by importing your WebSecurityConfigurerAdapter
class.
@WebMvcTest(controllers = SecuredController.class)
@Import(SecuredControllerTest.Config.class)
class SecuredControllerTest {
@Configuration
@EnableWebSecurity
static class Config extends MyWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("pa$$").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("pa$$").roles("ADMIN");
}
}
...
}
The embedded static class Config
is just to change where we get the users from, in this case an inMemoryAuthentication
will be enough.
Upvotes: 1
Reputation: 52746
In test class, use annotations
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
in setup test method
@Before
In real test method
@WithMockUser("spring")
@Test
Testing Spring Security like these examples
https://spring.io/blog/2014/05/23/preview-spring-security-test-web-security
https://www.baeldung.com/spring-security-integration-tests
Upvotes: 0