-1

I got some problem with Junit (Spring Security 6.5), I have an API Register to testing which already work well when test with Postman (fully output), When test with Junit, I got test fail with error http code 401 instead of 200:

Test code:

@WebMvcTest(AuthenticationController.class)
class AuthenticationControllerTest {

    @Autowired
    private MockMvc mockMvc;

    // ... Another Mock & Quired

    @Test
    void testRegister() throws Exception {
        String username = "example";
        String password = "exPw123";
        String email = "[email protected]";

        AuthenticationRequest request = new AuthenticationRequest(username, password, email);
        UserDto userDto = new UserDto(username, email);
        User user = Mockito.mock(User.class);

        Mockito.when(user.getDto()).thenReturn(userDto);
        Mockito.when(authenticationService.register(any(), any(), any(), any())).thenReturn(user);

        mockMvc.perform(post("/api/auth/v1/register")
                .with(csrf())
                .header("role", "learner")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(request)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.email").value(email))
                .andExpect(jsonPath("$.username").value(username));
    }
}

and securityFilterChain:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .securityMatcher("/**")
                .authorizeHttpRequests(auth -> {
                    auth.requestMatchers("/api/auth/**", "/swagger-ui/*", "/v3/api-docs*/**", "/swagger-resources/*", "/swagger-ui.html", "/").permitAll();
                    auth.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll();
                    auth.requestMatchers("/learner/**").hasAnyRole("LEARNER", "ADMIN");
                    auth.requestMatchers("/admin/**").hasAnyRole("ADMIN");
                    auth.anyRequest().authenticated();
                })
                .oauth2ResourceServer(
                        oauth2 -> oauth2.jwt(
                                jwtConfigurer -> jwtConfigurer
                                        .jwtAuthenticationConverter(jwtAuthenticationConverter())))
                .addFilterBefore(jwtCookieFilter, UsernamePasswordAuthenticationFilter.class)
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.disable()));

        return http.build();
    }

Detail problem:

  • In the test code, if I add "@AutoConfigureMockMvc(addFilters = false)", the test is simply pass with fully output (but I can't use this bc requirement not allow it)
  • So, with the test code I paste in upper, it fail with 401 even rule for "api/auth/**" is .permitAll()
  • I've try to add @WithMockUser" and JWT, but there still a problem when the response json is empty

Here is output log test (401):

MockHttpServletResponse:
           Status = 401
    Error message = Unauthorized
          Headers = [WWW-Authenticate:"Basic realm="Realm"", X-Content-Type-Options:"nosniff", X-XSS-Protection:"0", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

And 200 with @WithMockUser (@WithMockJWT):

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"0", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

What's wrong with my test config?

1

1 Answer 1

0

You got a 401 running your test because with @WebMvcTest, Spring does not load your security configuration. So, on your test class AuthenticationControllerTest, you should add an @Import with the configuration class that define your securityFilterChain bean. If the securityFilterChain bean is not in context, Spring uses defaults where all endpoints require authentication.

Also annotate your test method with @WithMockUser.

Hope this helps

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.