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

Mockito模拟RestTemplate postForEntity时CaptchaResponse.success始终为false

问题分析与解决

核心问题

你的测试mock未生效,控制器实际在调用真实的reCAPTCHA接口而非mock对象,导致success字段始终为false。原因有两点:

  1. 控制器内直接实例化RestTemplate(new RestTemplate()),未通过依赖注入获取实例,测试中mock的RestTemplate根本没被用到。
  2. CaptchaResponse的注解配置可能影响RestTemplate的反序列化逻辑。

解决方案

1. 修改控制器,注入RestTemplate

将RestTemplate改为依赖注入,让Spring能在测试时替换为mock对象:

@RestController
@RequiredArgsConstructor
public class RegisterController {
    ...
    private final String secret = "";
    private final String url = "https://www.google.com/recaptcha/api/siteverify";
    private final UserService userService;
    private final VerificationTokenService tokenService;
    private final MailingService mailingService;
    // 新增:注入RestTemplate
    private final RestTemplate restTemplate;
    ...
    @PostMapping("/api/auth/register")
    public ResponseEntity<RestUser> register(@Valid @RequestBody User user, @RequestParam("token") String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("secret", secret);
        map.add("response", token);
        // 移除:不再手动实例化RestTemplate
        // RestTemplate restTemplate = new RestTemplate();
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
        ResponseEntity<CaptchaResponse> response = restTemplate.postForEntity(url, request, CaptchaResponse.class);
        ...
    }
    ...
}

2. 修正测试类的Mock配置

将@Mock改为@MockBean,确保mock对象被Spring注入到控制器中:

@SpringBootTest
public class RegisterControllerTest {
    private MockMvc mock;
    @Autowired
    private RegisterController registerController;
    @Autowired
    private ObjectMapper objectMapper;
    @MockBean
    private UserService userService;
    @MockBean
    private VerificationTokenService tokenService;
    @MockBean
    private MailingService mailingService;
    // 修改:@Mock改为@MockBean
    @MockBean
    private RestTemplate restTemplate;
    private static User registeringUser;
    ...
    @Test
    @DisplayName("Test registration of a lambda user for production condition with valid captcha.")
    public void testRegisterProduction_shouldReturnRestUser_whenCaptchaSuccess() throws Exception {
        String token = "valid-token";
        RestUser expectedRest = new RestUser(registeringUser);
        VerificationToken expectedToken = new VerificationToken();
        CaptchaResponse captchaResponse = new CaptchaResponse();
        captchaResponse.setSuccess(true);
        ResponseEntity<CaptchaResponse> responseEntity = new ResponseEntity<>(captchaResponse, HttpStatus.OK);
        
        // 绑定mock行为到注入的restTemplate
        when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), eq(CaptchaResponse.class))).thenReturn(responseEntity);
        // 补充mock后续服务方法,避免空指针
        when(userService.save(any(User.class))).thenReturn(registeringUser);
        when(tokenService.save(any(VerificationToken.class))).thenReturn(expectedToken);
        doNothing().when(mailingService).sendVerificationEmail(any(User.class), anyString());
        
        mock.perform(post("/api/auth/register")
                .param("token", token)
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(registeringUser)))
                .andExpect(status().isOk());
    }
}

3. 修复CaptchaResponse的序列化配置

移除无用的@RequiredArgsConstructor,添加无参构造器确保RestTemplate能正确反序列化:

@NoArgsConstructor
@Getter
@Setter
@ToString
public class CaptchaResponse {
    private boolean success;
    private String challengeTs;
    private String hostname;
    private String[] errorcodes;
}

为什么这些修改有效

  • 控制器通过依赖注入获取RestTemplate后,测试中的@MockBean才能替换真实实例,mock的postForEntity行为才会生效。
  • @MockBean会将mock对象注册到Spring上下文,而@Mock仅创建局部mock对象,无法被控制器获取。
  • @NoArgsConstructor确保RestTemplate的消息转换器能通过反射创建CaptchaResponse实例,正确解析响应数据。

内容的提问来源于stack exchange,提问作者newenpoi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:17:36