0

I have a Spring Boot application that uses Spring Security to protect routes. Every time a user tries to access an endpoint, it goes through a security filter to authenticate the user. Now, I would like to create an integration test for a controller using MockMvc.

I've followed the official documentation, but I keep getting errors related to a custom bean from the WebSecurityConfig and its related dependencies. I've tried various combinations of annotations such as @SpringBootTest, @WebMvcTest, @ContextConfiguration, and @AutoConfigureMockMvc, but I can't seem to get it working.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class CsrfShowcaseTests {

@Autowired
private WebApplicationContext context;

private MockMvc mvc;

@Before
public void setup() {
    mvc = MockMvcBuilders
            .webAppContextSetup(context)
            .apply(springSecurity()) 1
            .build();
}

...

My goal is to have a controller integration test that tests only the controller layer, mocks dependencies, and uses a mock user (@WithMockUser) to pass the authentication filters.

Can anyone provide guidance on how to set up an integration test that meets these requirements?

Nathan
  • 45
  • 1
  • 6
  • You aren't following the documentation, at least not for Spring BOot. If you would you would be using `@SpringBootTest` (for a full integration test) or `@WebMvcTest` for a sliced test. Which is what you apparently want. Ditch all the annotations you have now an add `@WebMvcTest(YourController.class)` and ditch your `setup` method as well and just `@Autowired` on your `MockMvc` field. Now use `@WithMockUser` (or provide credentials in the request) to specify the user. – M. Deinum Apr 04 '23 at 10:26
  • @M.Deinum Thank you for the answer. Using your approach, it fails to load the application context. Error not being able to create bean with name jwtRequestFilter, which is a custom filter i add before UsernamePasswordAuthenticationFilter. – Nathan Apr 04 '23 at 12:49
  • Which is something you need to fix, which is probably done by adding some mocks for services it needs. – M. Deinum Apr 04 '23 at 13:49

1 Answers1

1

spring-security-test dependency provides good support for mocking users for integration tests..

You can use


@WithAnonymousUser or @WithMockUser 

Apart from this, to run the integration test you can :

  • Either use (this will enable complete context and you can mock the service layer using @MockBean):
@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
  • Or use can try using below setup :
@ExtendWith(SpringExtension.class)
@WebMvcTest(YourController.class)
@AutoConfigureMockMvc(addFilters = false)
@ImportAutoConfiguration(classes = {SecurityConfig.class})

Hope this helps..

Ayush
  • 21
  • 4
  • When i use the first option it does not behave correctly. When executing a method without a @WIthMockUser, instead of getting 403 on a protected route, i get 200. And when using the second option with all of the annotations, the application context can not be loaded and i get an error related to not being able to create bean with name jwtRequestFilter which is a custom filter i created. Kind of blocked now. – Nathan Apr 04 '23 at 12:46
  • You can try adding this custom filer in the list of classes for autoconfiguration .. in place or in addition to SecurityConfig.class as mentioned above – Ayush Apr 05 '23 at 09:10
  • Also, when you are using @WithMockUser, you can try defining restricted roles etc for the dummy username ..as part of configuration.. and hope that will give you the desired 403... – Ayush Apr 05 '23 at 09:12
  • Apparently i need to create a custom spring security configuration without the filter. – Nathan Apr 08 '23 at 18:43