【问题标题】:Unit Testing with jUnit and Mockito for External REST API calls使用 jUnit 和 Mockito 进行外部 REST API 调用的单元测试
【发布时间】:2015-07-26 06:50:52
【问题描述】:

我正在 Spring Boot Java 应用程序中为服务类构建单元测试。

服务类对返回 JSON 响应的 REST API 服务进行外部调用。我正在使用 Mockito 模拟这个电话。我在 mockserver 响应中对 JSON 进行硬编码。

在单元测试中硬编码 JSON 是一种不好的做法吗?如果 JSON 结构发生变化,那么测试应该失败是我的推理。是否有更好的最佳实践来执行此操作?

以下示例代码段:

实际的代码是功能性的,我只是编辑了这个 sn-p 它为简洁起见,所以如果您发现任何错误,请发表评论:

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

【问题讨论】:

  • JUnit 告诉我设置方法必须是静态的。 withSuccess() 方法定义在哪里?
  • 问题 - 您的 classUnderTest 是否公开 /Users/ API 或者它是否从外部服务调用外部 REST 端点 (/Users/)?

标签: java spring unit-testing junit mockito


【解决方案1】:

我目前和你在同一条船上,我的推理如下: 创建一个虚拟的 JSON 响应就像模拟一个对象并使用 Mockito.when 控制它。当您更改某些内部解析或期望不同的结果时,您需要更改 when().thenReturn() 调用中的任何内容。这与更改调用和更改对象表示的 JSON 响应相同。

因此,我的猜测是这很好。阅读有关测试 REST API 的各种文章后,普遍认为创建虚拟 JSON 响应是一种很好的做法。最佳做法是(不时)下载真正的 JSON 响应并将其作为模拟响应插入。通过这种方式,您可以让您的测试与外部方保持同步,而无需互联网请求即可运行测试。

按要求编辑:

【讨论】:

  • 嘿,蒂姆,您介意用一些您仅用作参考的来源编辑您的帖子吗?
  • 您好 Anataliocs,我添加了一些我找到的参考资料。希望他们帮助你=]
  • 太棒了,非常感谢。这让我对自己的方法更有信心,因为糟糕的单元测试几乎比他们所说的没有测试更糟糕;)
【解决方案2】:

我想说明另一种考虑的方法,即创建 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);

【讨论】:

  • 我什至没有想到这一点。我非常喜欢这种方法。感谢您的意见。
猜你喜欢
  • 2020-01-17
  • 2019-12-28
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 2017-09-19
相关资源
最近更新 更多