测试Spring Boot RestTemplate客户端的JSON映射

时间:2019-02-12 13:10:31

标签: java spring-boot junit resttemplate

我需要在Spring Boot应用程序中使用的REST API(由另一个遥远的团队提供)不在我的控制范围内。

当前,我想针对我的RestTemplate调用产生的请求(不是响应)编写一个测试,该测试与远程端的预期完全一致。我有一个示例JSON代码段,我想从我的代码中复制-给出与示例代码相同的参数,我应该在请求正文中得到一个等效的JSON代码段,然后我想对其进行分析以确定。

到目前为止,我的想法是让RestTemplate在我的控制下使用服务器,然后捕获JSON请求。显然,MockRestServiceServer是一个不错的选择。

这是正确的方法吗?如何配置MockRestServiceServer允许我执行此操作?

3 个答案:

答案 0 :(得分:4)

如果您只想验证JSON映射,则始终可以直接使用Jackson的ObjectMapper,并使用JSONassert之类的库来验证序列化的字符串是否匹配,从而验证对象结构是否匹配您的预期结果。例如:

@Autowired
private ObjectMapper objectMapper;
private Resource expectedResult = new ClassPathResource("expected.json");

@Test
public void jsonMatches() {
    Foo requestBody = new Foo();
    String json = objectMapper.writeValueAsString(requestBody);
    String expectedJson = Files
        .lines(expectedResult.getFile())
        .collect(Collectors.joining());
    JSONAssert.assertEquals(expectedJson, json, JSONCompareMode.LENIENT);
}

该测试仅使用ObjectMapper来验证JSON映射,因此,您甚至可以执行此操作而无需在测试中实际引导Spring引导(这可能更快)。这样做的缺点是,如果您使用的是与杰克逊不同的框架,或者RestTemplate更改了其实现,则该测试可能会过时。


或者,如果您对验证整个请求是否匹配(URL,请求方法,请求正文等)感兴趣,则可以使用MockRestServiceServer。这可以通过在测试中添加@SpringBootTest批注,自动装配RestTemplate和调用RestTemplate的服务来完成,例如:

@RunWith(SpringRunner.class)
@SpringBootTest
public class FooServiceTests {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private FooService fooService; // Your service

    private MockRestServiceServer server;

    @Before
    public void setUp() {
        server = MockRestServiceServer.bindTo(restTemplate).build();
    }
}

然后您可以使用以下方法设置测试:

@Test
public void postUsesRestTemplate() throws IOException, URISyntaxException {
    Path resource = Paths.get(getClass().getClassLoader().getResource("expected-foo.json").toURI());
    String expectedJson = Files.lines(resource).collect(Collectors.joining());
    server.expect(once(), requestTo("http://example.org/api/foo"))
        .andExpect(method(HttpMethod.POST))
        .andExpect(MockRestRequestMatchers.content().json(expectedJson))
        .andRespond(withSuccess());
    // Invoke your service here
    fooService.post();
    server.verify();
}

答案 1 :(得分:1)

根据文档,您可以使用Mock上的json路径来匹配请求。例如;

RestTemplate restTemplate = new RestTemplate()
 MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();

server.expect(ExpectedCount.once(), requestTo(path))
                .andExpect(method(HttpMethod.POST))
                .andExpect(jsonPath("$", hasSize(1)))
                .andExpect(jsonPath("$[0].someField").value("some value"))

注意:我尚未对此进行测试。

但是我已经实现了您使用Wire Mock多次寻找的目标。与MockRestServiceServer相比,这再次是一个更好的选择。我为什么这么说?

  • 广泛采用和支持
  • 更优雅,更广泛的请求和响应匹配
  • 高度可配置
  • 记录和播放
  • 可配置的安全性/身份验证
  • 您甚至可以将其泊坞窗

看看http://wiremock.org/docs/request-matching/

答案 2 :(得分:1)

如果您想手动检查一次,我认为您使用存根服务器(您可以使用WireMock)的方法很好。

或者,您可以在您的RestTemplate中添加一个request logger来记录每个请求。这样可以在出现问题时更容易地检查发​​送的请求是否正确。