在Spring-Rest中编写行为JUnit测试有什么意义?

时间:2017-10-11 12:21:51

标签: java spring unit-testing junit mockito

我是JUnit mockito的新手,我为Spring rest资源编写了这个测试函数。

@Test
public void getAllMessageHappyTest() throws Exception {
    List<Message> messageList = new ArrayList<>();
    messageList.add(new Message(1,"Hello"));
    messageList.add(new Message(5,"Hello world"));
    messageList.add(new Message(3,"Hello World, G!"));

    when(messageService.getAllMessages()).thenReturn(messageList);
    RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/messages/").accept(MediaType.APPLICATION_JSON);
    MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn();

   String expected = ""; // expected
   JSONAssert.assertEquals(expected,mvcResult.toString(),false);
}

在上面的场景中,我when(messageService.getAllMessages()).thenReturn(messageList);返回messageList由我(或团队成员)写的,我正在比较返回的{{ 1}} JSON也将由我(或由团队的同一成员)撰写 。所以这两件事都是由同一个人写的,所以进行这种测试有什么意义。

1 个答案:

答案 0 :(得分:1)

如果我正确地理解了这个问题,那么问题就在于此;因为编写测试的人也硬编码(以JSON字符串的形式),期望测试可能是多余的,或者至少可能是有限的价值。也许你的问题的子文本是因为谁写了底层端点将提供期望然后它必须通过,如果它的成功是预先确定的那么它没什么价值。

但是,无论是谁编写测试以及谁编写测试代码,上面显示的示例测试都有价值,因为:

  • 它测试的不仅仅是重新调整的JSON,还测试了......
    • REST端点映射是正确的,即它公开了一个名为"/messages/"的接受JSON的端点
    • REST层正在使用生成一些JSON
    • 的序列化程序
  • 继续运行此测试用例将确保即使在您(或您团队的其他成员)不再使用此代码之后,或者换句话说,此端点的预期行为仍将继续存在;它充当回归安全网。
  • 将来可能会更改被测代码,如果是这样,那么此测试用例提供了可以进行未来开发的基准。
  • 测试用例为您的代码提供了一种文档形式;不熟悉此代码库的人可以查看测试以了解代码的行为方式。

此外,此测试用例可以扩展为包括对无效路径进行测试,例如无效的回复,不安全的访问尝试等,从而提高测试覆盖率。

更新1 :回复此评论:

  

即使有人在实际代码中进行了更改,现在在使实际代码生成不同类型的JSON(假设不是必需的)之后,即使那时测试用例也会通过,因为那时硬编码并且预期也是硬编码的。那有什么意义呢?

这样的测试显然毫无意义:

String json = "...";

when(foo.getJson()).thenReturn(json);

assertEquals(json, foo.getJson());

这是您的测试所做的事情。相反,您的测试断言响应(以JSON的形式)与您模拟的messageService.getAllMessages()返回的响应的序列化形式相匹配。因此,您的测试涵盖了序列化部分以及Spring MVC层的各个方面,例如端点 - &gt;控制器映射以及拦截器和过滤器(如果有的话)。