Search code examples
javaspring-bootspring-securityintegration-testingunauthorized

Spring Boot Integration Test with Security


I am following a Spring Boot Integration Test tutorial I found, and it contains the following test:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class EmployeeControllerIntegrationTest
{
    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate rest;

    @Test
    public void test_Get_200() throws Exception
    {
        ResponseEntity<?> response = this.rest.getForEntity("http://localhost:" + port + "/employee", List.class);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    }
}

However, I have Spring Security enabled, so this test returns 401 instead of 200.

In case it's relevant, here is the Security Configuration of my main application:

@Configuration
public class SecurityConfig
{
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception
    {
        http
                .csrf().disable() // Do NOT do this in real life.
                .authorizeHttpRequests((authz) -> authz
                        .anyRequest().authenticated()
                )
                .httpBasic(withDefaults());
        return http.build();
    }
}

I don't have any special test configuration files. I am using an H2 in-memory database.

I tried using @WithMockUser or @WithAnonymousUser, but neither worked (I still get a 401). I know the API itself works, because I have manually tested it. When manually logging in and requesting a GET from the http://localhost:8088/employee endpoint, it works perfectly. It's the test that doesn't work, for some reason.

What am I missing here?

Thank you very much in advance for any help!


Solution

  • ChatGPT came to the rescue and found a solution.

    Turns out, you have to include a valid username and password in the request header, like so:

    ResponseEntity<?> response = this.rest.withBasicAuth("RealUser", "RealPassword").getForEntity("http://localhost:" + port + "/employee", List.class);
    

    All I did was add this

    withBasicAuth("RealUser", "RealPassword")
    

    to my original code.

    With only this addition, the test passed without problem.