我需要在Spring Boot应用程序中使用的REST API(由另一个遥远的团队提供)不在我的控制范围内。
当前,我想针对我的RestTemplate调用产生的请求(不是响应)编写一个测试,该测试与远程端的预期完全一致。我有一个示例JSON代码段,我想从我的代码中复制-给出与示例代码相同的参数,我应该在请求正文中得到一个等效的JSON代码段,然后我想对其进行分析以确定。
到目前为止,我的想法是让RestTemplate在我的控制下使用服务器,然后捕获JSON请求。显然,MockRestServiceServer
是一个不错的选择。
这是正确的方法吗?如何配置MockRestServiceServer允许我执行此操作?
答案 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
相比,这再次是一个更好的选择。我为什么这么说?
答案 2 :(得分:1)
如果您想手动检查一次,我认为您使用存根服务器(您可以使用WireMock)的方法很好。
或者,您可以在您的RestTemplate中添加一个request logger来记录每个请求。这样可以在出现问题时更容易地检查发送的请求是否正确。