You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot JUnit集成测试中注册接口404报错的修复方法

问题

在Spring Boot项目中编写JUnit集成测试,测试AuthController的注册接口时,运行shouldRegisterForAdmin方法出现404 User Name testadmin not found error错误,错误发生在mock AuthenticationManager的返回语句处。

AuthController注册方法

public ResponseEntity<AuthResponse> register(@RequestBody RegisterRequest registerRequest) {

    var registeredUser = authService.register(registerRequest);

    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(registeredUser.getUsername(), registerRequest.getPassword());
    Authentication auth = authenticationManager.authenticate(authToken);
    SecurityContextHolder.getContext().setAuthentication(auth);
    String jwtToken = jwtTokenProvider.generateJwtToken(auth);

    AuthResponse authResponse = AuthResponse.builder()
            .accessToken(jwtToken)
            .message("success")
            .build();

    return new ResponseEntity<>(authResponse, HttpStatus.CREATED);
}

RegisterRequest构造方法

public RegisterRequest getRegisterRequest(){
    return RegisterRequest.builder()
            .username("testadmin")
            .password("testadmin")
            .countryCode("1")
            .lineNumber("1234567890")
            .firstName("First Name Admin")
            .lastName("Last Name Admin")
            .email("testadmin@afet.com")
            .organizationId(1L)
            .build();
}

测试类代码

@SpringBootTest
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc(addFilters = false)
class AuthControllerTest {

    private final String ADMIN_CONTROLLER_BASEURL = "/api/v1/admin";

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    private AuthService authService;

    @Mock
    private PasswordEncoder passwordEncoder;

    @Mock
    private JwtTokenProvider jwtTokenProvider;

    @Mock
    private AuthenticationManager authenticationManager;

    @Mock
    private SecurityContext securityContext;

    @Test
    void shouldRegisterForAdmin() throws Exception {
   
        // Given
        RegisterRequest registerRequest = new UserBuilder().getRegisterRequest();

        User user = new UserBuilder()
                .withRegisterRequest(registerRequest,passwordEncoder).build();

        UserDTO userDto = UserDTO.builder()
                .username(user.getUsername())
                .firstName(user.getFirstName())
                .lastName(user.getLastName())
                .userRole(user.getUserRole())
                .countryCode(user.getCountryCode())
                .lineNumber(user.getLineNumber())
                .userStatus(user.getStatus())
                .email(user.getEmail())
                .lastLoginDate(user.getLastLoginDate())
                .build();


        AuthResponse authResponse = new AuthResponseBuilder()
                .withMessage("success")
                .withAccessToken("test_token")
                .build();


        // when
        when(authService.register(registerRequest)).thenReturn(userDto);

        when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class)))
                .thenReturn(new UsernamePasswordAuthenticationToken(userDto.getUsername(),registerRequest.getPassword())); // ERROR LINE
        when(jwtTokenProvider.generateJwtToken(any(Authentication.class))).thenReturn("test_token");

        SecurityContextHolder.setContext(securityContext);

        // then - Perform the POST request and assert the response
        mockMvc.perform(post(ADMIN_CONTROLLER_BASEURL + "/register")
                        .contentType("application/json")
                        .content(objectMapper.writeValueAsString(registerRequest)))
                .andDo(print())
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.accessToken").value(authResponse.getAccessToken()))
                .andExpect(jsonPath("$.message").value(authResponse.getMessage()));

    }
}

错误行

when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class)))
        .thenReturn(new UsernamePasswordAuthenticationToken(userDto.getUsername(),registerRequest.getPassword()));

解决方案
  • 修正AuthenticationManager的mock方式:测试类中AuthenticationManager使用@Mock只会创建普通mock对象,不会替换Spring容器中的真实实例。AuthController注入的真实AuthenticationManager会尝试去数据库查找testadmin(但该用户仅通过mock的AuthService返回,并未实际入库),因此触发"用户未找到"错误。将@Mock改为@MockBean,让Spring容器使用mock实例替代真实实现:

    @MockBean
    private AuthenticationManager authenticationManager;
    
  • 返回已认证的Authentication对象:当前mock返回的UsernamePasswordAuthenticationToken是通过(principal, credentials)构造器创建的,默认处于未认证状态,后续逻辑(如JwtTokenProvider生成token)可能需要已认证对象。推荐使用带权限参数的构造器创建已认证token:

    when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class)))
            .thenReturn(new UsernamePasswordAuthenticationToken(
                    userDto.getUsername(),
                    registerRequest.getPassword(),
                    Collections.singletonList(new SimpleGrantedAuthority("ROLE_ADMIN")) // 根据实际角色调整
            ));
    

    也可以手动设置认证状态:

    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDto.getUsername(), registerRequest.getPassword());
    authToken.setAuthenticated(true);
    when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class)))
            .thenReturn(authToken);
    
  • 测试后清理SecurityContext(可选):避免当前测试的SecurityContext状态影响其他测试:

    @AfterEach
    void tearDown() {
        SecurityContextHolder.clearContext();
    }
    

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:43:20