npm npm Build Status Coverage Status Known Vulnerabilities style NPM

api-contract-validator

此断言库插件用于根据 Swagger/OpenAPI 定义验证 API 响应模式。

使用此插件很简单。只需将插件指向您的 API 定义文件路径,并在集成测试中添加一行代码来验证您的应用程序是否符合其设计合约。

亮点

  • 根据 API 定义文档进行断言
  • 描述性断言失败
  • 简单易用的用法
  • 覆盖率报告(可以打印到您的终端或导出到 json 文件)
  • 支持从 axiossuperagentsupertestrequestlight-my-request(由 fastify 使用)返回的响应格式
  • 支持 OpenAPI 3.0
  • 支持多个定义文件

它是如何工作的?

api-contract-validator 会根据提供的 API 文档文件将您的 API 定义转换为基于 json-schema 的模式。然后,每当调用 matchApiSchema 断言时,它会自动从您调用的 API 请求返回的响应对象中提取方法、路径和状态码,并验证响应对象。响应头和主体都会被验证。

如何使用?

安装

> npm i --save-dev api-contract-validator

Chai.js

const matchApiSchema = require('api-contract-validator').chaiPlugin;
const path = require('path');
const { expect, use } = require('chai');

// API definitions path
const apiDefinitionsPath = path.join(__dirname, 'myApp.yaml'); 

// add as chai plugin
use(matchApiSchema({ apiDefinitionsPath }));

it('GET /pets/123', async () => {
    const response = await request.get('/pet/123');
    expect(response).to.have.status(200).and.to.matchApiSchema();

    // alternatively pass
    const { statusCode, headers, body } = response
    expect({
        path: '/pet/123',
        method: 'get',
        status: statusCode,
        body: body,
        headers: headers,
    }).to.have.status(200).and.to.matchApiSchema();
})

Should.js

const matchApiSchema = require('api-contract-validator').shouldPlugin;

// API definitions path
const apiDefinitionsPath = path.join(__dirname, 'myApp.yaml');

// add as should plugin
matchApiSchema(should, { apiDefinitionsPath });

it('GET /pets/123', async () => {
    const response = await request.get('/pet/123');
    should(response).have.status(200).and.matchApiSchema();
})

Jest

const matchApiSchema = require('api-contract-validator').jestPlugin;

// API definitions path
const apiDefinitionsPath = path.join(__dirname, 'myApp.yaml');

// add as jest plugin
matchApiSchema({ apiDefinitionsPath });

it('GET /pets/123', async () => {
    const response = await request.get('/pet/123');
    expect(response).toHaveStatus(200);
    expect(response).toMatchApiSchema();
})

多个 api 定义文件

使用带有文件路径数组的 apiDefinitionsPath 选项

const apiDefinitionsPath = [path.join(__dirname, 'myApp.yaml'), path.join(__dirname, 'myApp2.yaml')];

描述性断言失败

AssertionError: expected response to match API schema
+ expected - actual

{
    "body": {
-    "age": -1
+    "age": "should be >= 0"
+    "name": "should have required property"
    }
    "headers": {
-    "x-expires-after": []
-    "x-rate-limit": -5
+    "x-expires-after": "should be string"
+    "x-rate-limit": "should be >= 0"
    }
}

覆盖率报告

通过在插件选项中提供标志 reportCoverage:true,插件会生成所有未覆盖 API 定义的报告。

use(matchApiSchema({
    apiDefinitionsPath,
    reportCoverage: true
}));
* API definitions coverage report *

Uncovered API definitions found:
*ROUTE*                    | *METHOD*   | *STATUSES* 
/v2/pet                    | POST       | 405        
/v2/pet                    | PUT        | 400,404,405
/v2/pet/findByStatus       | GET        | 200,400    
/v2/pet/findByTags         | GET        | 200,400    
/v2/pet/:petId             | GET        | 400,404    
/v2/pet/:petId             | POST       | 405        
/v2/pet/:petId             | DELETE     | 400,404    
/v2/pet/:petId/uploadImage | POST       | 200         

导出报告

当提供 exportCoverage: true 时,将在您的 cwd 中创建具有以下结构的 coverage.json 文件

use(matchApiSchema({
    apiDefinitionsPath,
    exportCoverage: true
}));

coverage.json

[{"route":"/v2/pet","method":"POST","statuses":"405"},
{"route":"/v2/pet","method":"PUT","statuses":"400,404,405"},
{"route":"/v2/pet/:petId","method":"GET","statuses":"200"},
{"route":"/v2/pet/:petId","method":"POST","statuses":"405"},
{"route":"/v2/pet/:petId","method":"DELETE","statuses":"404"}]

支持的请求库

  • supertest
  • axios
  • request-promise*
  • 更多即将推出

* 使用 request-promise 时,必须将 resolveWithFullResponse:true 添加到请求选项中,以便正确提取请求详细信息

支持的断言库

  • chai.js
  • should.js
  • jest
  • 更多即将推出