使用 Mockito 正确地对 postForEntity(返回 ResponseEntity<DTO>)进行存根

问题描述 投票:0回答:1

我目前在测试期间遇到奇怪的行为,

目标是测试以下注册方法:

@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;

    ...

    @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);
        
        // Preparing the request and extracts the response content.
        RestTemplate restTemplate = new RestTemplate();
        
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
        ResponseEntity<CaptchaResponse> response = restTemplate.postForEntity(url, request, CaptchaResponse.class);
        CaptchaResponse captchaResponse = response.getBody();
        
        // Response is 200 OK (during test).
        System.out.println(response);
        
        // The body contains CaptchaResponse (during test).
        System.out.println(response.getBody());
        
        // Always false (during test) even with mocking.
        System.out.println(captchaResponse.isSuccess());

        // If the captcha failed (always fails during tests).
        if (captchaResponse == null || !captchaResponse.isSuccess()) return ResponseEntity.badRequest().build();
        
        ...
        
        // Returns the programmed rest user (without the disclosure of the token) as a positive response.
        return ResponseEntity.ok(u);
    }
    
    ...
}

到目前为止,编写的测试是:

@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
    private RestTemplate rest;
    
    // We don't want to repeat ourselves.
    private static User registeringUser;
    
    @BeforeAll
    public static void initialize() {
        List<Role> defaultRoles = new ArrayList<Role>();
        defaultRoles.add(new Role("USER"));
        
        // Classic user that will attempt to register.
        registeringUser = new User("[email protected]", "newenpoi", ".azerty");
        registeringUser.setRoles(defaultRoles);
    }
    
    @BeforeEach
    public void setup() {
        MockitoAnnotations.openMocks(this);
        mock = MockMvcBuilders.standaloneSetup(registerController).build();
    }

    @Test
    @DisplayName("Test registration of a lambda user for production condition with valid captcha.")
    public void testRegisterProduction_shouldReturnRestUser_whenCaptchaSuccess() throws Exception {
        // Given.
        String token = "valid-token";
        
        RestUser expectedRest = new RestUser(registeringUser);
        VerificationToken expectedToken = new VerificationToken();
        
        // Simulate captcha response.
        CaptchaResponse captchaResponse = new CaptchaResponse();
        captchaResponse.setSuccess(true);
        
        ResponseEntity<CaptchaResponse> responseEntity = new ResponseEntity<>(captchaResponse, HttpStatus.OK);
        
        // When.
        when(rest.postForEntity(anyString(), any(HttpEntity.class), eq(CaptchaResponse.class))).thenReturn(responseEntity);
        
        // Then.
        mock.perform(post("/api/auth/register").param("token", token).contentType("application/json").content(objectMapper.writeValueAsString(registeringUser))).andExpect(status().isOk());
    }
}

无论我尝试做什么,captchaResponse 中的成功字段都将始终保持 false,并且我无法找到测试中缺少的内容以通过

if (captchaResponse == null || !captchaResponse.isSuccess())
条件!

这是 CaptchaResponse 对象供参考:

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

我尽力遵循良好实践,调试确实打印了包含 CaptchaResponse 的响应,但 isSuccess() 在测试期间将始终为 false,并且即使我在测试期间明确设置值,其他字段仍保持为空(我只保留上面测试就成功了)。

我一直在 Stack 上四处浏览,但遗憾的是我找不到针对此行为的具体解决方案。

非常感谢任何为我指明正确方向的帮助!

java testing junit mockito stubbing
1个回答
0
投票

您在

RestTemplate
中创建
RegisterController
的新实例,并在测试中创建
RestTemplate
bean 的模拟。 尝试注入一个由 Spring 管理的 bean。

@RestController
@RequiredArgsConstructor
public class RegisterController {

private final RestTemplate restTemplate;
© www.soinside.com 2019 - 2024. All rights reserved.