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?