我有一个不受我控制的 REST API(由另一个遥远的团队提供),我需要从 Spring Boot 应用程序中使用它。
目前我想编写一个测试,以确保我的 RestTemplate 调用产生的请求(不是响应)与远程端的预期完全一致。我有一个示例 JSON 片段,我想从我的代码中复制它 - 给定与示例中相同的参数,我应该在请求正文中得到一个等效的 JSON 片段,然后我想对其进行分析以确定。
到目前为止,我的想法是让 RestTemplate 使用我控制的服务器,然后捕获 JSON 请求。显然 MockRestServiceServer
是一个不错的选择。
这是正确的方法吗?如何配置 MockRestServiceServer 以允许我执行此操作?
最佳答案
如果您只对验证 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 boot(这可能会更快)。这样做的缺点是,如果您使用的框架与 Jackson 不同,或者如果 RestTemplate
更改其实现,则该测试可能会过时。
或者,如果您有兴趣验证完整请求是否匹配(URL、请求方法、请求正文等),您可以使用您提到的 MockRestServiceServer
。这可以通过将 @SpringBootTest
注释添加到您的测试、 Autowiring 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();
}
关于java - 测试 Spring Boot RestTemplate 客户端的 JSON 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54650873/