I'm trying to test the home controller
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
I'm using spring security using as username "user" and test as password by default but @PreAuthorize is not working
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@PreAuthorize("hasRole('ADMIN')")
public class HomeControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
@WithMockUser(username = "user", password = "test", roles = "ADMIN")
public void home() throws Exception {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World!");
}
}
The result
Expected result:
<"[Hello World!]">
Actual result:
<"{"timestamp":1501100448216,"status":401,"error":"Unauthorized","message":"Full
authentication is required to access this resource","path":"/"}]">
Am I missing something?
Try to add the following to your test class:
@TestExecutionListeners(mergeMode = MergeMode.MERGE_WITH_DEFAULTS, listeners = {
WithSecurityContextTestExecutionListener.class
})
And the following dependency if you don't have it:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
Spring security require an extra listener that is not present in tests by default so you need to tell spring to add it by specifing the @TestExecutionListeners
annotation in merge
mode so it will merge the current listed listeners with the listeners you want to add - in this case WithSecurityContextTestExecutionListener
You used invaild password, because
The default AuthenticationManager has a single user (‘user’ username and random password, printed at INFO level when the application starts up) doc
You can create custom user and do test againe
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("admin").password("passAdmin").roles("USER", "ADMIN").build());
return manager;
}