Mock WebClient Post方法时.body处出现NullPointerException问题
问题:Mock WebClient Post方法时在.body()处触发NullPointerException
在Mock WebClient的Post方法时,执行到.body(Mono.just(createReq), CreateReq.class)处出现NullPointerException。已确认createReq不为空,尝试将请求体改为字符串形式(.body(req, String.class))后仍触发该异常。
业务代码
public class RepoService { @Autowired private WebClient webClient; public DIResponse createIdentity(DICreateRequest diCreateRequest) { CreateReq createReq = diCreateRequestMapper.setRequest(diCreateRequest); DIResponse diResponse = null; UriComponents uriBuilder = UriComponentsBuilder .fromUriString(url) .build(false); DIResponse apiResponse = webClient .post() .uri(uriBuilder.toUriString()) .body(Mono.just(createReq), CreateReq.class) // 此处触发NullPointerException .retrieve() .onStatus(HttpStatus::is4xxClientError, clientResponse -> clientResponse.bodyToMono(DIBadRequest.class).flatMap(errorResponse -> { LOGGER.error(CLIENT_ERROR, "POST", clientResponse.statusCode(), errorResponse); return Mono.error(new DataAccessException(ERROR_STATUS +clientResponse.statusCode()+ ERROR_DESC+ errorResponse.getDetail())); })) .bodyToMono(DIResponse.class) .block(); return apiResponse; } }
JUnit测试用例
@Mock private WebClient webClient; @Mock WebClient.RequestHeadersUriSpec requestHeadersUriSpecMock; @Mock WebClient.RequestBodyUriSpec requestBodyUriSpecMock; @Mock WebClient.RequestBodySpec requestBodySpecMock; @Mock WebClient.RequestHeadersSpec requestHeadersSpecMock; @Mock WebClient.ResponseSpec responseSpecMock; @InjectMocks private RepoService repositoryService; @Test void testCreateIdentity() throws IOException { DICreateRequest mockDICreateRequest = getMockDICreatReq(); CreateReq createReq = createDI(); DIResponse mockDIResponse = getDI(); when(diCreateRequestMapper.setRequest(mockDICreateRequest)).thenReturn(createReq); when(webClient.post()).thenReturn(requestBodyUriSpecMock); when(requestBodyUriSpecMock.uri((URI) any())).thenReturn(requestBodySpecMock); when(requestBodySpecMock.body(any())).thenReturn(requestHeadersSpecMock); when(requestHeadersSpecMock.retrieve()).thenReturn(responseSpecMock); when(responseSpecMock.onStatus(any(), any())).thenReturn(responseSpecMock); Mockito.when(responseSpecMock.bodyToMono(DIResponse.class)).thenReturn(Mono.just(mockDIResponse)); DIResponse result = repositoryService.createIdentity(mockDICreateRequest); Assert.assertEquals(mockDIResponse.getId(), result.getId()); }
解决方案
问题根源
测试用例存在两处Mock匹配错误:
body()方法重载不匹配:业务代码调用的是body(Publisher<? extends T>, Class<T>)重载,但测试仅Mock了body(Object)版本,导致实际调用时无对应Mock返回,返回null触发NPE。uri()方法参数类型不匹配:业务代码传入的是String类型的URI,但测试Mock的是URI对象类型的参数,导致匹配失败,后续调用链中断返回null。
修复代码
修改测试用例中的两处Mock语句:
- 修正
uri()方法的Mock,匹配String类型参数:
// 替换原有的when(requestBodyUriSpecMock.uri((URI) any())).thenReturn(requestBodySpecMock); when(requestBodyUriSpecMock.uri(anyString())).thenReturn(requestBodySpecMock);
- 修正
body()方法的Mock,匹配正确的重载:
// 替换原有的when(requestBodySpecMock.body(any())).thenReturn(requestHeadersSpecMock); when(requestBodySpecMock.body(any(Publisher.class), eq(CreateReq.class))).thenReturn(requestHeadersSpecMock);
如果后续需要测试字符串请求体的场景,补充对应的Mock:
when(requestBodySpecMock.body(any(Publisher.class), eq(String.class))).thenReturn(requestHeadersSpecMock);
修改后重新运行测试,即可解决NullPointerException问题。
内容的提问来源于stack exchange,提问作者mathew thomas
相关产品推荐
相关产品推荐

