【问题标题】:Test Rest API involving DB calls using Mockito使用 Mockito 测试涉及数据库调用的 Rest API
【发布时间】:2018-02-26 23:27:01
【问题描述】:

我需要对基于 REST 的应用程序 API 进行一些单元测试。

例如,如果 API 如下所示

 @RequestMapping(value = "/todo/{id}", method = RequestMethod.GET)
public ResponseEntity<ToDo> getToDoById(@PathVariable("id") long id) throws ToDoException{
    //Makes DB call
    ToDo toDo = toDoService.getToDoById(id);
 }

上述 API 执行 DB 调用以从数据库中获取 ID。

当我这样做的时候

 mockMvc.perform(MockMvcRequestBuilders.get("/todo/3")
 .accept(MediaType.APPLICATION_JSON)

它将访问数据库。

现在,这种方式的模拟越来越多地成为到达端点的集成测试。这是正确的做法吗,否则

  1. 什么是使用 Mockito 进行单元测试并打击 DB 或 Web 服务等外部实体的正确方法

  2. 如何模拟数据库,如果被模拟,我如何获取数据库数据。

【问题讨论】:

  • 在测试你的控制器时,你需要模拟所有的服务调用。
  • 那很酷的答案.. 但我看到了一个示例,其中使用 @Autowired private WebApplicationContext wac; 没有任何模拟服务调用,但结果可用
  • 他们可能正在加载完整的应用上下文,并使用它。他们可能正在加载模拟 bean 或测试 bean。
  • @pvpkiran: 如果在服务调用之后有任何以下 helper.get 方法调用,它们也应该被模拟吗?

标签: java rest mockito


【解决方案1】:

正如@pvpkiran 提到的,如果你测试一个单元,你就模拟了这个单元的引用。因此,在这种情况下回答您的问题:

使用 Mockito 进行单元测试并击中外部实体(如 DB 或 Web 服务)的正确方法是什么?

在单元测试中将模拟对象定义为类属性:

ToDoService toDoService = Mockito.mock(ToDoService.class)

然后告诉 Mockito 如何对特定调用做出反应(在设置方法中或在您的测试方法中):

ToDo toDo = new ToDo(...);
//configure your todo object to satisfy your needs
Mockito.when(toDoService.getToDoById(123l)).thenReturn(toDo); //returns the created object only if called with 123l

Mockito.when(toDoService.getToDoById(Matchers.anyLong())).thenReturn(toDo); //returns the created object for a call with any long value

如何模拟数据库,如果模拟了如何获取数据库数据?

在这种情况下,您模拟了整个服务。如果您想测试 DAO,Spring(您显然使用)提供了一个嵌入式数据库,您可以使用 sql 脚本进行配置。见 documentation.

【讨论】:

  • 很酷,知道了。我可以知道是否有任何状态代码 2000 可用,我的应用程序 API 返回相同。是有效的还是 200
  • 假设你的意思是http状态码,我认为它被定义为3位数。见 [en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success]。通常,如果一切正常,Spring mvc 默认返回 200。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-13
  • 2011-11-12
  • 2015-07-26
  • 1970-01-01
  • 2015-02-19
  • 2011-09-30
  • 2019-12-23
相关资源
最近更新 更多