JUnit测试中如何通过@WithMockUser方式模拟密码错误的用户?
@WithMockUser 无法覆盖密码错误/用户不存在的测试场景
使用@WithMockUser时,底层会调用WithMockUserSecurityContextFactory#createSecurityContext方法生成包含模拟用户的安全上下文,但这种方式生成的认证对象始终处于已认证状态,完全跳过了密码验证逻辑,因此无法测试密码错误、用户不存在这类需要完整认证流程的场景。
相关代码实现
SecurityConfiguration 类
@Bean public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) { String encPW = passwordEncoder.encode("123456"); log.debug(encPW); UserDetails user = User.withUsername("user") .password(encPW) //.password("123456") .roles("USER") .build(); UserDetails admin = User.withUsername("admin") .password(passwordEncoder.encode("123456")) .roles("USER", "ADMIN") .build(); return new InMemoryUserDetailsManager(user, admin); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf((csrf) -> csrf.ignoringRequestMatchers("/demo/**")) .authorizeHttpRequests((ah) -> ah .requestMatchers("/demo/authenticate").authenticated() .anyRequest().permitAll() ) .httpBasic(Customizer.withDefaults()) ; return http.build(); }
测试代码
//@WithMockUser(username = "no_exist_user", password = "123456777") // 此注解无效,会直接跳过认证流程 @Test void testHelloByWrongPw() throws Exception { mvc.perform( post("/demo/authenticate") .with(httpBasic("no_exist_user", "123456777")) .content("{\"a1\":\"123\"}") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .queryParam("a1","123") ) .andExpect(status().isUnauthorized()); }
关键说明
@WithMockUser本质是直接在安全上下文中植入一个已认证的用户,不会触发Spring Security的完整认证流程(包括密码校验、用户信息查询)。如果要测试密码错误、用户不存在这类场景,必须使用httpBasic()模拟真实的HTTP Basic认证请求,这样才能让系统走完整的认证逻辑,返回预期的401 Unauthorized状态码。
内容的提问来源于stack exchange,提问作者shawnliu
相关产品推荐
相关产品推荐

