上次我们已经搞定了逻辑层的单元测试,这次我们来康康接口层的单元测试。接口层主要负责的就是请求的处理,最常见的就是 HTTP 请求的处理。

但针对 接口层 的单元测试其实是可以五花八门的。它并不像逻辑层和数据层一样的通用,对于它的测试往往有很多路可以走。

由于使用的 HTTP 框架不同,单元测试的实现方式则不同。 既可以通过程序来模拟 HTTP 请求,也可以通过真实的 HTTP 请求来测试,通过借助外部的一些测试工具来实现。

所以本文只能给出一种思路,具体的实现方式还是要根据实际的框架来实现。

环境

gin
  • 不需要启动路由服务
  • 复用已有的项目内的请求结构

代码

由于之前已经贴过,所以 service 层的 代码这里就不赘述了

base case

mockgen -source=./user.go -destination=../mock/user_service_mock.go -package=mock

单元测试

基础代码非常简单,就是我们常见的,最重要的让我们来看看单元测试应该怎么写

工具方法

在编写实际单元测试之前,我们需要一些工具方法来帮助我们构建一些请求。

既然我们不想启动路由,其实最关键的问题就在如何构建一个 gin.Context 来模拟正常的请求。

gin.CreateTestContexthttp.NewRequest

单元测试

GetUserRequest

可以看到测试方法如出一辙,再详细的话只需要对请求的返回值做解析然后进行断言即可。

问题

当然以上述方式来实现单元测试的话,是会遗漏一些问题,毕竟偷懒是要有代价的。

  • 路由路径的问题:可以看到上述的单元测试中并没有注册对应的 url 地址,那么实际中可能会由于代码路由的书写错误而导致 404 的情况
  • 请求结构字段错误:由于我们复用了原有代码中的请求结构,即使单词拼写错误依然能成功,因为两边都一样错,所以即使字段名称与接口文档不一致也无法发现。

针对这两个问题,我觉得可以由更加上层的测试来保证,由于这里仅仅是单元测试,我觉得这些代价还是可以接受的。并且,如果是使用 swagger 生成文档的情况下,也能保证文档和代码的统一性。但在此还是要出来提个醒,毕竟实际问题我还是遇到过的。

优化点

当然,这里的举例还是过于简单,实际中的请求往往会比较复杂。

  • 实际场景往往一些请求需要鉴权,这个可以在根据实际你的鉴权方式在前面添加中间件统一来处理登录就可以
  • 其他类型的请求也是类似的如 PUT、DELETE 等
  • 当前只是简单的处理了正常的 200 HTTP Code 还会出现其他异常的情况也需要按实际接口进行处理

总结

通常从现象来说,这一层的测试往往发现的问题比较少,是由于这一层的逻辑少,测试下来最常见的问题往往就是字段名称和限制条件不满足需求。所以其实从性价比的角度来说,单独对这层拿出来测试往往比较低,故实际中见到的比较少。

不过话又说回来了,本文的目的不仅仅是为了让你了解到可以这样写单元测试,其中使用的方法往往还能再某些时候让你复用 handler 的方法来保证系统的一致性。