如何在MockRestServiceServer中验证JSON请求主体

时间:2020-01-28 16:38:57

标签: java spring spring-boot

我的应用程序序列化了各种模型,并通过HTTP请求将它们发送给第三方。

我想根据集成测试将请求主体反序列化为该模型或那个模型,然后对其进行断言。看起来有些人可能实现了自己的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)
....

像这样可能吗?我有什么选择?

3 个答案:

答案 0 :(得分:1)

您可以使用MockRestRequestMatchers.jsonPath来验证属性,以验证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());

答案 1 :(得分:0)

我最终写了一个使用杰克逊ggplot(dataset2, aes(x=Region, y= male)) + geom_bar(stat='identity') 并拿下RequestMatcher的单个ObjectMapper。这样,我可以反序列化为expectedObject的类型,并通过字段比较来做一个字段。

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;
        }
    }
}

答案 2 :(得分:0)

如果你只需要一次就可以使用 lambda

ByteArrayOutputStream bos = new ByteArrayOutputStream();
...
.andExpect(clientHttpRequest -> bos.write(((ByteArrayOutputStream) clientHttpRequest.getBody()).toByteArray()))
...
相关问题