I have controller like this
@RestController
@RequestMapping(value="/test")
@PreAuthorize("hasRole('ADMIN')")
public class TestController
{
@RequestMapping( method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> test ()
{
return ResponseEntity.ok("test");
}
}
I tried to write unit test that will test permissions to access this controllers method.
This is my test
@RunWith(SpringRunner.class)
@ContextConfiguration
@WebMvcTest(value = TestController.class)
public class AUnitTest
{
@Autowired
private MockMvc mockMvc;
private final String url = "/test";
@Test
@WithMockUser(roles="ADMIN")
public void testAdminUser() throws Exception
{
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(this.url );
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
}
}
When I remove roles from @WithMockUser and leave empty, by default it will have role USER and then test passes. When I put roles USER and ADMIN, it will also pass because of USER role. But whenever I set role to ADMIN it will fail, even though I set that user needs to have ADMIN role to access controller.
I tried with setting username, password, everything from Spring Security Docs, etc.
Am I missing something?
Method-level security is implemented by placing the @PreAuthorize annotation on controller methods (actually one of a set of annotations available, but the most commonly used). This annotation contains a Spring Expression Language (SpEL) snippet that is assessed to determine if the request should be authenticated.
Spring Security provides method level security using @PreAuthorize and @PostAuthorize annotations. This is expression-based access control. The @PreAuthorize can check for authorization before entering into method. The @PreAuthorize authorizes on the basis of role or the argument which is passed to the method.
With the @SpringBootTest annotation, Spring Boot provides a convenient way to start up an application context to be used in a test.
The global method security functionality is disabled by default. To enable it, you use the @EnableGlobalMethodSecurity annotation over the configuration class of your application. You can apply authorization rules that the application checks before the call to a method.
Try to add @EnableGlobalMethodSecurity(prePostEnabled = true)
to test class.
Or add config sth like that:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Config {
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With