前后端分离:使用 mest 做契约测试跟踪 API 接口变更

Posted phodal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前后端分离:使用 mest 做契约测试跟踪 API 接口变更相关的知识,希望对你有一定的参考价值。

还在担心后端 API 变更对前端的影响?快来使用 mest

在实施前后端分离架构的过程中,最让人苦恼的莫过于:API 发生了变化。API 发生变化的原因那可是相当的丰富:业务变化、字段名出错、第三方接口不匹配等等,但是这些都不重要——一个字段从 string 变成了 number,对于前端的影响并不大。

重要的是,后台 API 发生了一些变化,而前端却不知道或者没有人对此作出相应——比如说,某一天你下班了,后台的同事告诉了你,这个 API 变了。结果,第二天这事被忘记了,因此就轻而易举地就创造了一堆 bug。

契约与契约测试

过去,前后端约定好的 API 可能以文档的形式定义,当发生 API 变更的时候,可能以邮件、聊天工具等等不同的形式来通知 API 的消费方。但是,这种方式容易出现问题,比如说:不能通知到团队的所有人、或者相关的消息埋没在消息流中。为此,人们发明了一种以 JSON 作为契约的方式来作为契约好的 API 接口。

前后端分离:使用 mest 做契约测试跟踪 API 接口变更

契约,是以双方当事人互相对立合致的意思表示所构成的,其中包括要约及承诺两个基本的意思表示。

即,对于前端和后台来说,这个契约就是最后以 JSON 形式展现的 API。它可以用于前端开发时使用的接口,也是后端最后要提供的线上 API 格式:

 
   
   
 
  1. {

  2.  "id": 9,

  3.  "title": "搭建指南",

  4.  "make": {

  5.  "id": 8,

  6.  "category": 9,

  7.  "featured_image": "uploads/make/.thumbnails/guide-map.jpg/guide-map-600x360.jpg"

  8.  },

  9.  "slug": "搭建指南"

  10. }

有了契约,前端不会被前端 Block,可以在后台接口还没开发好的情况下,继续开发工作——只需要在后期做一些集成工作即可。一般来说,对于这样一个契约(接口),它会包含大部分的 API 可能响应的情况,如 200 返回的是正常情况,404 返回 Not Found,401 返回权限异常。这个时候,我们只需要有一个 Mock Server 就可以了,在这个 Mock Server 里,只要能处理 参数、授权等等的内容即可。

然而,契约只是一种承诺,它并不能保证接口提供方能完成遵循这个契约开发。对于接口的提供来说,需要一个有效的机制来验证后台的接口是与契约对齐、一致的。

于是,就有了契约测试的概念。

契约测试

契约测试(Contract Test),又称为消费者驱动的契约测试(Consumer-Driven Contracts,简称CDC),顾名思义就是对契约进行测试。

由于后端是 API 的提供者,因而在维护契约上,后端也拥有了更多的责任——主要用于验证接口是否稳定。因而在选型的时候,多数以后端的技术栈为主,如 Java 系列,如 Spring Cloud Contract 就是一个不错的方式。

无论采用怎样的方式,它都在一定的程度上保证后端 API 与契约的一致性。

那么,对于前端呢?

前端契约测试:Mest 方式

对于前端来说,要追踪这样的一个契约并不是一件容易的事。过去,要对契约对待测试,无非就是将其写到正常的测试中,验证字段是否一致。直到,我看到了 interface 的时候有了一些想法。

引子:使用 interface 进行 API 类型检查

TypeScript 提供了一个 interface 这样的类型。在写 Angular 代码的时候,为了进行类型检测,我们会写一个 interface 来获取相应的值:

 
   
   
 
  1. this.http.get<IUserResponse>('https://api.github.com/users/phodal')

  2.  .subscribe(

  3.  data => this.githubUser = data,

  4.  err => console.log(err)

  5.  );

使用的时候,只需要:

 
   
   
 
  1. <div *ngIf="this.githubUser">

  2.  <p><img [src]="this.githubUser.avatar_url" alt="" width="80" height="80"></p>

  3.  <p>{{this.githubUser.company}}</p>

  4.  <p>{{this.githubUser.bio}}</p>

  5. </div>

即这里的 IUserResponse 是一个 interface,然而这个类型检测在构建完后,并不能自动展示出来。

可能你也想到了,这里的 interface 可以直接用来校验后台 API 是否与 interface 一致。

于是,我们需要一个更高级的手段来做这样的事,这就是 mest 框架要做的,哈~。

对,我撸了一个新的框架,mest。先来看看用法:

Mest 前端测试契约: CLI 模式

CLI 模式,其实是我早期验证是否可以工作的时候,留下来的接口。它可以验证一些公开的 API 是否是可以访问的,不需要编写任何代码。

  1. 首先只需要安装 mest

 
   
   
 
  1. npm install -g mest

  1. 然后编写一个简单的 csv 文件,里面映射有 URL 和接口路径:

 
   
   
 
  1. url,interface

  2. https://phodal.github.io/mest-test/error.json,mock/IError.ts

  3. https://phodal.github.io/mest-test/moreerror.json,mock/IMoreIError.ts

  4. https://phodal.github.io/mest-test/user.json,mock/IUser.ts

然后,就可以运行命令进行测试了:

 
   
   
 
  1. mest -i data/url.csv

完了,将会显示对应的结果:

 
   
   
 
  1. -> API https://phodal.github.io/mest-test/error.json .

  2. -> API https://phodal.github.io/mest-test/moreerror.json .

  3. -> API https://phodal.github.io/mest-test/user.json .

  4. same key: login,id,avatar_url,url,html_url,followers_url,following_url,gists_url,starred_url,subscriptions_url,organizations_url,repos_url,events_url,received_events_url,type,site_admin,name,company,blog,location,email,hireable,bio,public_repos,public_gists,followers,following,created_at,updated_at

  5. local diff key: avatar_id, remote diff: gravatar_id

Mest 前端测试契约:API 调用

当然,除了对于大部分的契约来说,它们都是需要一系列复杂的交互,才能进行下一步的对比。这个时候,一个比较简单的方式,就是直接调用这些 API:

 
   
   
 
  1. yarn add mest

然后直接对响应的结果进行处理即可,就可以直接进行断言。

 
   
   
 
  1. let mest = new Mest()

  2. let results: IDiff = mest.localCompareInterface('mock/IError.ts', {

  3.  id: 233333,

  4.  key: 'ssfd',

  5.  messages: '2010-11-08T11:46:51Z',

  6.  documentation_url: 2

  7. })

  8. expect(results).toEqual({

  9.  diff: {

  10.  local: ['message'],

  11.  remote: ['key', 'messages']

  12.  },

  13.  diffTypes: [],

  14.  same: ['id', 'documentation_url']

  15. })

对,就是这么简单,只需要一个 Interface 就可以验证 API 的 key 是否一致,以及 value 的类型是否一致。

结论

原理其实很简单,就是获取 interface 的 key-value,以及 API 的 key-value 进行对比。

TypeScript 大法好,Mest 大法好


以上是关于前后端分离:使用 mest 做契约测试跟踪 API 接口变更的主要内容,如果未能解决你的问题,请参考以下文章

Swagger - 前后端分离后的契约

北京-第四十二期前后端分离与不分离的工作流程分别是怎样的

前后端分离:RESTful API和HTTP动词

asp.net怎么实现前后端分离 asp.net如何实现前后端分离

前后端分离后,RESTful API 最佳实践

前后端分离开发模式下后端质量的保证 —— 单元测试