Chai HTTP Build Status semantic-release

使用 Chai 断言进行 HTTP 集成测试。

特性

  • 集成测试请求组合
  • 测试 HTTP 应用或外部服务
  • 针对常见 HTTP 任务的断言
  • chai expectshould 接口

安装

这是 Chai 断言库 的一个附加插件。可以通过 npm 安装。

npm install chai-http

插件

像使用其他 Chai 插件一样使用此插件。

var chai = require('chai')
  , chaiHttp = require('chai-http');

chai.use(chaiHttp);

要在网页上使用 Chai HTTP,只需包含 dist/chai-http.js 文件。

<script src="chai.js"></script>
<script src="chai-http.js"></script>
<script>
  chai.use(chaiHttp);
</script>

集成测试

Chai HTTP 通过 superagent 提供了一个用于实时集成测试的接口。为此,您首先必须构建一个对应用程序或 URL 的请求。

构建完成后,您将获得一个可链式调用的 API,它允许您指定要调用的 HTTP VERB 请求(get、post 等)。

应用程序 / 服务器

您可以使用函数(如 express 或 connect 应用程序)或 node.js http(s) 服务器作为请求的基础。如果服务器未运行,chai-http 将找到一个合适的端口供特定测试监听。

注意:此功能仅在 Node.js 上受支持,不在 Web 浏览器中支持。

chai.request(app)
  .get('/')

app 传递给 request 时,它会自动打开服务器以接收传入请求(通过调用 listen()),并在发出请求后,服务器会自动关闭(通过调用 .close())。如果您想保持服务器打开,例如,如果您正在进行多个请求,您必须在 .request() 后调用 .keepOpen(),并手动关闭服务器。

var requester = chai.request(app).keepOpen()

Promise.all([
  requester.get('/a'),
  requester.get('/b'),
])
.then(responses => ....)
.then(() => requester.close())

URL

您也可以使用基本 URL 作为请求的基础。

chai.request('https://#:8080')
  .get('/')

设置请求

使用给定 VERB(get、post 等)创建请求后,您可以将这些附加方法链式调用以创建请求。

方法 目的
.set(key, value) 设置请求头
.send(data) 设置请求数据(默认类型为 JSON)
.type(dataType) 更改从 .send() 方法发送的数据类型(xml、form 等)
.attach(field, file, attachment) 附加文件
.auth(username, password) 为基本身份验证添加身份验证头
.query(parmasObject) 链式调用一些 GET 参数

示例

.set()

// Set a request header
chai.request(app)
  .put('/user/me')
  .set('Content-Type', 'application/json')
  .send({ password: '123', confirmPassword: '123' })

.send()

// Send some JSON
chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })

.type()

// Send some Form Data
chai.request(app)
  .post('/user/me')
  .type('form')
  .send({
    '_method': 'put',
    'password': '123',
    'confirmPassword': '123'
  })

.attach()

// Attach a file
chai.request(app)
  .post('/user/avatar')
  .attach('imageField', fs.readFileSync('avatar.png'), 'avatar.png')

.auth()

// Authenticate with Basic authentication
chai.request(app)
  .get('/protected')
  .auth('user', 'pass')

.query()

// Chain some GET query parameters
chai.request(app)
  .get('/search')
  .query({name: 'foo', limit: 10}) // /search?name=foo&limit=10

处理响应 - 传统方式

在以下示例中,我们使用 Chai 的 Expect 断言库。

var expect = chai.expect;

要发出请求并断言其响应,可以使用 end 方法。

chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })
  .end(function (err, res) {
     expect(err).to.be.null;
     expect(res).to.have.status(200);
  });
注意事项

因为 end 函数传递了一个回调函数,所以断言是异步执行的。因此,必须使用一种机制来通知测试框架回调已完成。否则,测试将在检查断言之前通过。

例如,在 Mocha 测试框架 中,这是通过使用 done 回调函数 实现的,它表示回调已完成,并且可以验证断言。

it('fails, as expected', function(done) { // <= Pass in done callback
  chai.request('https://#:8080')
  .get('/')
  .end(function(err, res) {
    expect(res).to.have.status(123);
    done();                               // <= Call done to signal callback end
  });
});

it('succeeds silently!', function() {   // <= No done callback
  chai.request('https://#:8080')
  .get('/')
  .end(function(err, res) {
    expect(res).to.have.status(123);    // <= Test completes before this runs
  });
});

当传递 done 时,Mocha 会等待调用 done(),或者直到 超时 过期。当表示完成时,done 还接受一个错误参数。

处理响应 - Promise

如果 Promise 可用,request() 将变成一个支持 Promise 的库,并且可以链式调用 then

chai.request(app)
  .put('/user/me')
  .send({ password: '123', confirmPassword: '123' })
  .then(function (res) {
     expect(res).to.have.status(200);
  })
  .catch(function (err) {
     throw err;
  });

注意:Node.js 版本 0.10.x 和一些较旧的 Web 浏览器没有原生 Promise 支持。您可以使用任何符合规范的库,例如

// Add promise support if this does not exist natively.
if (!global.Promise) {
  global.Promise = require('q');
}
var chai = require('chai');
chai.use(require('chai-http'));

在每次请求中保留 cookie

有时您需要保留来自一个请求的 cookie,并在下一个请求中发送它们(例如,当您想使用第一个请求登录,然后稍后访问一个仅供身份验证的用户访问的资源时)。为此,可以使用 .request.agent()

// Log in
var agent = chai.request.agent(app)
agent
  .post('/session')
  .send({ username: 'me', password: '123' })
  .then(function (res) {
    expect(res).to.have.cookie('sessionid');
    // The `agent` now has the sessionid cookie saved, and will send it
    // back to the server in the next request:
    return agent.get('/user/me')
      .then(function (res) {
         expect(res).to.have.status(200);
      });
  });

注意:由 chai.request.agent(app) 启动的服务器在测试结束后不会自动关闭。您应该在测试后调用 agent.close() 以确保程序退出。

断言

Chai HTTP 模块为 expectshould 接口提供了许多断言。

.status (code)

  • @param {Number} 状态码

断言响应具有提供的状态码。

expect(res).to.have.status(200);

.header (key[, value])

  • @param {String} 头部键(不区分大小写)
  • @param _{String RegExp}_ 头部值(可选)

断言 ResponseRequest 对象具有头部。如果提供了值,则断言与值相等。您也可以传递正则表达式进行检查。

注意:在 Web 浏览器中运行时,同源策略 仅允许 Chai HTTP 读取 某些头部,这会导致断言失败。

expect(req).to.have.header('x-api-key');
expect(req).to.have.header('content-type', 'text/plain');
expect(req).to.have.header('content-type', /^text/);

.headers

断言 ResponseRequest 对象具有头部。

注意:在 Web 浏览器中运行时,同源策略 仅允许 Chai HTTP 读取 某些头部,这会导致断言失败。

expect(req).to.have.headers;

.ip

断言字符串表示有效的 IP 地址。

expect('127.0.0.1').to.be.an.ip;
expect('2001:0db8:85a3:0000:0000:8a2e:0370:7334').to.be.an.ip;

.json / .text / .html

断言 ResponseRequest 对象具有给定的内容类型。

expect(req).to.be.json;
expect(req).to.be.html;
expect(req).to.be.text;

.charset

断言 ResponseRequest 对象具有给定的字符集。

expect(req).to.have.charset('utf-8');

.redirect

断言 Response 对象具有重定向状态码。

expect(res).to.redirect;
expect(res).to.not.redirect;

.redirectTo

  • @param _{String RegExp}_ 位置 URL

断言 Response 对象重定向到提供的地址。

expect(res).to.redirectTo('http://example.com');
expect(res).to.redirectTo(/^\/search\/results\?orderBy=desc$/);

.param

  • @param {String} 参数名称
  • @param {String} 参数值

断言 Request 对象具有一个具有给定键(可选)等于值的查询字符串参数。

expect(req).to.have.param('orderby');
expect(req).to.have.param('orderby', 'date');
expect(req).to.not.have.param('limit');
  • @param {String} 参数名称
  • @param {String} 参数值

断言 RequestResponse 对象具有一个具有给定键(可选)等于值的 cookie 头部。

expect(req).to.have.cookie('session_id');
expect(req).to.have.cookie('session_id', '1234');
expect(req).to.not.have.cookie('PHPSESSID');
expect(res).to.have.cookie('session_id');
expect(res).to.have.cookie('session_id', '1234');
expect(res).to.not.have.cookie('PHPSESSID');

发布

chai-http 使用 semantic-release 发布,并使用以下插件

许可证

(MIT 许可证)

版权所有 (c) Jake Luer jake@alogicalparadox.com

特此授予任何人免费获得本软件副本和相关文档文件(“软件”)的副本,不受限制地处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的权利,以及允许获得软件的人员这样做,但须符合以下条件:

以上版权声明和本许可声明应包含在软件的所有副本或重要部分中。

该软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、特定用途的适用性和非侵权保证。在任何情况下,作者或版权持有人均不对因软件或使用或其他处理软件而产生的任何索赔、损害或其他责任负责,无论是在合同、侵权或其他诉讼中,无论该责任是基于任何理论,还是源于或与软件有关。