MockServerRequest测试出现The mapper returned a null Mono错误求助
解决MockServerRequest测试中"The mapper returned a null Mono"空指针问题
问题背景
我在测试一个Handler方法时,通过以下方式创建MockServerRequest对象:
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.put("/rest/v1/templates/{id}", "1") .headers(headers) .contentType(MediaType.APPLICATION_JSON) .body(builder.build().writeValueAsString(templateRequest))); MockServerHttpResponse response = exchange.getResponse(); ServerRequest request = MockServerRequest.builder().uri(URI.create("/rest/v1/templates")) .pathVariable("id", "1").headers(headers).exchange(exchange).body(Mono.just(templateRequest));
采用这种方式是因为,用下面的方式创建的对象无法获取路径变量,导致方法执行失败:
ServerRequest request = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
该问题属于已知问题。
之后我将这个MockServerRequest传入Handler执行:
Mono<ServerResponse> putResponse = templateHandler.update(request); StepVerifier.create(putResponse).expectComplete().log().verify();
但触发了如下错误:
java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onError(java.lang.NullPointerException: The mapper returned a null Mono)) ...(完整错误栈内容同上)
解决方法
1. 排查Handler实现中的null Mono返回问题
这个错误的核心原因是templateHandler.update方法的某个分支返回了null,而非合法的Mono<ServerResponse>对象。你需要检查update方法的所有代码路径:
- 确保所有条件分支都返回有效的Mono,比如找不到资源时返回
ServerResponse.notFound().build(),出现业务异常时返回Mono.error(new RuntimeException("...")),绝对不能直接返回null。
2. 修正MockServerRequest的构建逻辑
你手动构建request时存在两处潜在问题:
- URI不匹配:原始请求的URI是带占位符的
/rest/v1/templates/{id},但你构建request时用了/rest/v1/templates,即使手动设置了pathVariable,也可能导致Handler内部路径匹配逻辑出错。建议改为具体的URI:/rest/v1/templates/1。 - 重复设置请求体:exchange已经包含了请求体内容,无需手动通过
.body(Mono.just(templateRequest))注入,这会导致request读取body时出现冲突。
修改后的构建代码:
ServerRequest request = MockServerRequest.builder() .uri(URI.create("/rest/v1/templates/1")) .pathVariable("id", "1") .headers(headers) .exchange(exchange) .build();
3. 调整StepVerifier断言逻辑
Mono<ServerResponse>会先发出一个响应元素,然后才会触发完成信号。你之前只用expectComplete()会忽略响应元素,可能掩盖问题,建议修改为验证响应状态:
StepVerifier.create(putResponse) .expectNextMatches(response -> response.statusCode().is2xxSuccessful()) .expectComplete() .log() .verify();
4. 升级Spring Framework版本解决路径变量问题
你遇到的路径变量无法获取的问题是旧版本的已知问题,已经在后续Spring Framework版本中修复。建议升级到5.3.x及以上版本,这样就可以用标准方式创建ServerRequest,避免手动构建的潜在风险:
ServerRequest request = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
内容的提问来源于stack exchange,提问作者Anadi Misra
相关产品推荐
相关产品推荐

