使用RestAssured(spring-mock-mvc)测试Controller时模拟CompletableFuture异常返回失败
问题分析与修复方案
嘿Dan,我一眼就看到两个可能导致测试失败的核心问题,咱们一个个说:
1. 请求参数传递方式不匹配(最直接的原因)
你的RegistrationResource里的register方法用@RequestBody String name接收参数,这意味着接口期望从请求体里读取name的值;但你的测试代码里用了.params("name", "dan")——这是把name作为URL查询参数/表单参数发送,接口根本拿不到正确的参数值,甚至可能触发了非预期的逻辑分支。
你需要把测试里的参数传递改成用请求体:
given() .body("dan") // 替换原来的params(),匹配@RequestBody的参数接收方式 .standaloneSetup(registrationResource) .when() .post("/players") ...
2. Mock服务未正确注入被测资源
你在测试里创建了mockedWhackAMoleService,但如果没有把这个mock实例注入到registrationResource中,被测代码调用的还是真实的whackAMoleService实现,自然不会触发你预设的异常逻辑。
测试方法开头一定要加上mock注入的逻辑:
// 假设你的RegistrationResource有setter方法,或者用构造函数注入 registrationResource.setWhackAMoleService(mockedWhackAMoleService);
修改后的完整测试代码
@Test public void shouldReturnConflictWhenPlayerAlreadyRegistered() { // 关键:将mock服务注入到被测资源实例中 registrationResource.setWhackAMoleService(mockedWhackAMoleService); CompletableFuture<Void> failFlow = new CompletableFuture<>(); failFlow.completeExceptionally(new CompletionException(new PlayerNameAlreadyRegisteredException( "Player already registered"))); when(mockedWhackAMoleService.register(any(String.class))).thenReturn(failFlow); given() .body("dan") // 用请求体传递参数,匹配@RequestBody .standaloneSetup(registrationResource) .when() .post("/players") .then() .statusCode(HttpStatus.CONFLICT.value()); }
额外验证小技巧
- 可以在被测方法
register里加个日志打印name的值,确认测试时能正确拿到"dan"; - 调试时检查
registrationResource.whackAMoleService的实例类型,确保是你创建的mock对象而非真实实现。
这样修改后,应该就能正确触发异常分支,返回预期的409状态码了!
内容的提问来源于stack exchange,提问作者danwag
相关产品推荐
相关产品推荐

