Java 如何在MockRestServiceServer中验证json请求正文
我的应用程序序列化各种模型,并通过HTTP请求将它们发送给第三方 我希望根据集成测试将请求主体反序列化为这个或那个模型,然后对其进行断言。看起来有些人可能会实现他们自己的Java 如何在MockRestServiceServer中验证json请求正文,java,spring,spring-boot,Java,Spring,Spring Boot,我的应用程序序列化各种模型,并通过HTTP请求将它们发送给第三方 我希望根据集成测试将请求主体反序列化为这个或那个模型,然后对其进行断言。看起来有些人可能会实现他们自己的RequestMatcher,或者只是针对字符串进行断言,但这两个选项看起来都很脏。如果我实现了我自己的RequestMatcher,我就必须为主体可能是的每个模型实现一个不同的RequestMatcher 如果我可以在请求体中反序列化json,并在声明性匹配内容之外对其执行我想要的操作,那就太好了 大概是这样的: BodyCa
RequestMatcher
,或者只是针对字符串进行断言,但这两个选项看起来都很脏。如果我实现了我自己的RequestMatcher
,我就必须为主体可能是的每个模型实现一个不同的RequestMatcher
如果我可以在请求体中反序列化json,并在声明性匹配内容之外对其执行我想要的操作,那就太好了
大概是这样的:
BodyCaptor captor = new BodyCaptor(); // I made this up
MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
mockServer
.expect(MockRestRequestMatchers.requestTo(testBaseUri + testApiPath))
.andExpect(method(HttpMethod.POST))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andCaptureBody(captor)
.andRespond(MockRestResponseCreators.withSuccess());
MyModel mymodel = objectMapper.deserialize(captor.getValue())
assertThat(mymodel.getWhateverProperty()).isEqualTo(5)
....
这样的事情可能吗?我的选项是什么?您可以使用验证json属性及其值来验证属性
mockServer
.expect(MockRestRequestMatchers.requestTo(testBaseUri + testApiPath))
.andExpect(method(HttpMethod.POST))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(MockRestRequestMatchers.jsonPath("$.property", Matchers.equalToIgnoringCase("value")))
.andRespond(MockRestResponseCreators.withSuccess());
最后,我编写了一个
请求匹配程序
,它使用了Jackson对象映射器
,并获取了一个预期对象
。通过这种方式,我可以反序列化到expectedObject
的类型,并进行字段对字段的比较
public class MyRequestMatcher implements RequestMatcher {
private static final Logger LOG = LoggerFactory.getLogger(MyRequestMatcher.class);
private Object expectedPayload;
private ObjectMapper objectMapper;
public MyRequestMatcher (Object expectedPayload, ObjectMapper objectMapper) {
this.expectedPayload = expectedPayload;
this.objectMapper = objectMapper;
}
@Override
public void match(ClientHttpRequest clientHttpRequest) throws IOException, AssertionError {
byte[] requestBodyBytes = ((ByteArrayOutputStream)clientHttpRequest.getBody()).toByteArray();
String requestBody = new String(requestBodyBytes, StandardCharsets.UTF_8);
Object actualPayload = objectMapper.readValue(requestBody, expectedPayload.getClass());
// do this in a try catch so we can log the meaningful message from our assertion
// library before rethrowing - otherwise it gets swallowed by mockServer
try {
assertThat(actualPayload).isEqualToComparingFieldByField(expectedPayload)
} catch (AssertionError error) {
LOG.error(error.getMessage());
throw error;
}
}
}
现在,我可以在测试中执行以下操作:
MyObject expectedPayload = new MyObject();
expectedPayload.setField1("expectedValueforField1");
expectedPayload.setField2("expectedValueforField2");
mockServer
.expect(MockRestRequestMatchers
.requestTo("http://myurl.com/mypath"))
.andExpect(new MyRequestMatcher(expectedPayload, objectMapper))
.andRespond(request -> {
return MockRestResponseCreators.withSuccess().createResponse(request);
});
如果你只需要它一次,你可以用一个lambda
ByteArrayOutputStream bos = new ByteArrayOutputStream();
...
.andExpect(clientHttpRequest -> bos.write(((ByteArrayOutputStream) clientHttpRequest.getBody()).toByteArray()))
...