我目前在测试期间遇到奇怪的行为,
目标是测试以下注册方法:
@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 上四处浏览,但遗憾的是我找不到针对此行为的具体解决方案。
非常感谢任何为我指明正确方向的帮助!
您在
RestTemplate
中创建 RegisterController
的新实例,并在测试中创建 RestTemplate
bean 的模拟。
尝试注入一个由 Spring 管理的 bean。
@RestController
@RequiredArgsConstructor
public class RegisterController {
private final RestTemplate restTemplate;