Describe the bug When testing a controller with WebMvcTest and Spring Security, the authorization seems to be failing. Testing the endpoint with no user returns a 401 as expected, but when a valid user is provided, it returns 404, not 200. Note that I have read through many different blogs and samples and the Spring Security documentation, in particular this section https://docs.spring.io/spring-security/reference/servlet/test/mockmvc/setup.html - of course there is a lot of information available but some is for older versions of Spring Security, or older versions of JUnit, or for Spring MVC, not Spring Boot... and so on, so it is quite difficult to figure out what is the right way to acutally write the tests, so please forgive if I have done it incorrectly. I went with the information from what seems to be the most authorative source - the docs linked above.
To Reproduce
This repository contains a small application that reproduces the issue. This was created from Sprng Initializr. Just clone the repo and run "mvn test".
Notice that the test fails and reports a HTTP 404.
For comparison, comment out the @WithMockUser annotation on the test method, and run it again. This time you will get a 401, which is expected.
https://github.com/markxnelson/spring-security-webmvctest-reproducer
Expected behavior I expect that the test as written should pass, i.e., it should authenticate as that user and have the necessary role to call the hello method, and therefore recieve back a response with HTTP 200.
Comment From: sjohnr
@markxnelson, I believe you have not annotated your application with @EnableMethodSecurity. I believe that will move you forward. I'm going to close this issue for now, but feel free to let me know if I've misunderstood your issue and we can re-open if needed.
If you simply have questions about testing, they would probably be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it).
Having said that, if you feel the docs could use enhancing, please feel free to open an enhancement with the specific details you feel are missing. We also welcome contributions if you learn during this process and want to enhance the docs (including to resolve an issue you open)! Just make sure to mention that you want to work on the issue.
Comment From: markxnelson
Thanks @sjohnr - I added that annotation and it still gives a 404. I believe I am following the docs correctly, so it seems to me to be a possible bug, not just a usage question. I am happy to go ask on Stack Overflow as well.
Comment From: markxnelson
here is the link to SO question: https://stackoverflow.com/questions/77018088/webmvctest-with-spring-security-seems-to-incorrectly-return-404-possible-bug
Comment From: sjohnr
Thanks @markxnelson. I have added an answer on the question. Note (for others) that it was specifically a testing issue of getting the right annotations on the test, which trips up a lot of folks (me included).
Comment From: markxnelson
Great, thanks @sjohnr I would like to contribute a doc update, but we do have a process to go through to make contributions (and to sign your CLA), so I need to do that first.
Comment From: sjohnr
Awesome, looking forward to having you as a contributor! Also, feel free to open the issue with your findings and a specific description of what you find missing in the docs. Even if you can't submit a PR, someone else may be able to, and you are still contributing.
Comment From: Sti2nd
I struggled with this as well. Did you create a PR @markxnelson?
We already used @WebMvcTest (from SpringBoot) and I would like to continue to use it. I tried following Spring security guide on how to setup for MockMvc, but it failed to load some ConfigurationProperties (even though I did use @EnableConfigurationProperties).
Eventually I found this GitHub issue and got it working with help from the example from Stack Overflow. This works for me: EDIT: Outdated example; see comment below.
@WebMvcTest
@EnableConfigurationProperties(CustomSecurityConfigProps::class)
@Import(CustomSecurityConfig::class)
class UserControllerTest {
private lateinit var client: MockMvc
// The following can actually be removed, see next comment
@BeforeEach
fun setup(context: WebApplicationContext) {
client = MockMvcBuilders
.webAppContextSetup(context)
.apply<DefaultMockMvcBuilder>(springSecurity())
.build()
}
@Test
@WithMockUser
fun `valid form returns Status 204`() {
...
}
}
Would be great to have an example of how to use Spring Security with @WebMvcTest in the official docs.
Comment From: Sti2nd
Well, I just read the following text on WebMvcTest.
By default, tests annotated with @WebMvcTest will also auto-configure Spring Security [...]
And sure enough, removing the custom MockMvc initializaition doesn't have an effect. I can see that Spring security is still somehow being loaded, and removing @WithMockUser makes the test return 403. So here is an updated example:
@WebMvcTest
@EnableConfigurationProperties(CustomSecurityConfigProps::class)
@Import(CustomSecurityConfig::class)
class UserControllerTest {
@Autowired
private lateinit var client: MockMvc
@Test
@WithMockUser
fun `valid form returns Status 204`() {
...
}
}