Java 使用 jUnit 和 Mockito 对外部 REST API 调用进行单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30240989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit Testing with jUnit and Mockito for External REST API calls
提问by anataliocs
I am building unit tests in a Spring Boot Java application for a service class.
我正在 Spring Boot Java 应用程序中为服务类构建单元测试。
The service class makes an external call to a REST API service that return a JSON response. I am mocking this call using Mockito. I am hardcoding a JSON in the mockserver response.
服务类对返回 JSON 响应的 REST API 服务进行外部调用。我正在使用 Mockito 嘲笑这个电话。我在模拟服务器响应中硬编码了一个 JSON。
Is this bad practice to have hardcoded JSONs in your unit tests? If the JSON structure changes, then the test should fail is my reasoning. Is there a better, best practice where to do this?
在单元测试中使用硬编码的 JSON 是不好的做法吗?如果 JSON 结构发生变化,那么测试应该失败是我的推理。是否有更好的最佳实践来执行此操作?
Example Snippet below:
下面的示例片段:
The actual code is functional, I just edited this snippet it for brevity to get the idea across, so post a comment if you see any errors:
实际代码是功能性的,为了简洁起见,我只是编辑了这个片段,如果你看到任何错误,请发表评论:
public class UserServiceTest extends TestCase {
private static final String MOCK_URL = "baseUrl";
private static final String DEFAULT_USER_ID = "353";
UserService classUnderTest;
ResponseEntity<Customer> mockResponseEntity;
MockRestServiceServer mockServer;
@Mock
RestTemplate mockRestTemplate;
public void setUp() throws Exception {
super.setUp();
classUnderTest = new UserRestService();
mockRestTemplate = new RestTemplate();
mockServer = MockRestServiceServer.createServer(mockRestTemplate);
ReflectionTestUtils.setField(classUnderTest, "restTemplate",
mockRestTemplate);
ReflectionTestUtils.setField(classUnderTest, "userSvcUrl",
MOCK_URL);
}
public void testGetUserById() throws Exception {
mockServer.expect(requestTo(MOCK_URL + "/Users/" + DEFAULT_USER_ID)).andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(
"{\n" +
" \"UserCredentials\": {\n" +
" \"Password\": \"\",\n" +
" \"PasswordNeedsUpdate\": false,\n" +
" \"Security\": [\n" +
" {\n" +
" \"Answer\": \"\",\n" +
" \"Question\": \"Why did the bicycle fall over?\"\n" +
" }\n" +
" ]\n" +
"}"
, MediaType.APPLICATION_JSON));
Customer customer = classUnderTest.getUserById(DEFAULT_USER_ID);
mockServer.verify();
assertNotNull(customer);
assertEquals(DEFAULT_USER_ID, customer.getId());
}
}
采纳答案by Tim van der Lippe
I am currently in the same boat as you and my reasoning was as follows:
Creating a dummy JSON-response is like mocking an object and controlling it using Mockito.when
. You would need to change anything in the when().thenReturn()
call when you changed some inner parsing or you expect different results. This is the same with a JSON-response where calls are changed and object representations are altered.
我目前和你在同一条船上,我的推理如下:创建一个虚拟的 JSON 响应就像模拟一个对象并使用Mockito.when
. when().thenReturn()
当您更改某些内部解析或期望不同的结果时,您需要更改调用中的任何内容。这与 JSON 响应相同,其中调用已更改且对象表示已更改。
Therefore my guess would be that this is fine. Reading various articles about testing REST API's, the general concensus is that creating dummy JSON-responses is good practice. Best practice would be to (from time to time) download the real JSON-response and insert this as the mocked response. This way you can keep your tests up-to-date with the external party, while the tests can run without internet requests.
因此,我的猜测是这很好。阅读有关测试 REST API 的各种文章,普遍的共识是创建虚拟 JSON 响应是一种很好的做法。最佳实践是(不时)下载真正的 JSON 响应并将其作为模拟响应插入。通过这种方式,您可以使您的测试与外部方保持同步,而测试可以在没有 Internet 请求的情况下运行。
Edit as requested:
按要求编辑:
Ruby - Stubbing external services,
Python - Testing a successful call
JavaScript - An example of AJAX testing
Ruby -存根外部服务,
Python -测试一个成功的调用
JavaScript - AJAX 测试示例
Python -最后一个关于模拟的谷歌教程
回答by Jose Martinez
I would like to shine a light on another approach to consider, and that is to create POJO (e.g. data model, JavBean) of the object that the JSON represents then using a JSON serializer, like Gson from Google, to convert it to a JSON String.
我想阐明另一种要考虑的方法,即创建 JSON 表示的对象的 POJO(例如数据模型、JavBean),然后使用 JSON 序列化程序(如 Google 的 Gson)将其转换为 JSON细绳。
UserCredentials uc = new UserCredentials ();
//set the values
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(uc);