HTTP 服务器测试库 supertest

 2016年05月02日    118     声明


supertest是一个HTTP 服务器测试模块,它让HTTP断言变得非常简单。它可以直接引入Express项目的app.js文件进行测试,也可以通过一个测试网址创建测试用例。你可以很容易的将它集成到Mocha测试框架中。


  1. 模块介绍与安装
  2. 使用示例
  3. API

1. 模块介绍与安装

supertest为测试HTTP的提供了一个高层次的抽象;当然你也可以使用其API还,以super-agent(超级代理)的模式进行较低层的测试。

模块安装

我们可以使用npm命令安装这上模块,并通过--save-dev参数将依赖关系保持到package.json文件的devDependencies节点中:

npm install supertest --save-dev

安装后,就可以在项目中使用require()方法引用这个模块:

var request = require('supertest');


2. 使用示例

你可以传入一个http.Server对象或Functionrequest()方法中,如果传入服务器对象还没有创建连接监听,SuperTest会为其创建一个临时的端口绑定。

SuperTest可以运行在任意测试框架中,如果不需要使用任何测试框架,可以像下面这样使用:

var request = require('supertest');
var express = require('express');
 
var app = express();
 
app.get('/user', function(req, res){
  res.status(200).json({ name: 'tobi' });
});
 
request(app)
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res){
    if (err) throw err;
  });

Mocha框架中,你可以任意.expect()目标方法中传入done参数,以在指定处理完成后进行回调:

describe('GET /user', function(){
  it('respond with json', function(done){
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);
  })
})

在以上示例中,我们添加了一个状态码200,如果不添加状态码SuperTest会将所有HTTP错误传递到第一个参数中。

如果使用了.end()方法,当.expect()断言中发生错误则不会抛出,而是会传递到.end()方法的回调函数中。所以,你可以像下面这样在.end()方法中重新跑出或使用done()回调:

describe('GET /users', function(){
  it('respond with json', function(done){
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect(200)
      .end(function(err, res){
        if (err) return done(err);
        done();
      });
  });
});

异常捕获是依次进行的,可以在断言发生前修改response响应体或响应头:

describe('GET /user', function(){
  it('user.name should be an case-insensitive match for "tobi"', function(done){
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect(function(res) {
        res.body.id = 'some fixed id';
        res.body.name = res.body.name.toUpperCase();
      })
      .expect(200, {
        id: 'some fixed id',
        name: 'TOBI'
      }, done);
  });
});
 

任何HTTP操作都可以在super-agent中进行。如,可以模拟一个文件上传操作:

request(app)
.post('/')
.field('name', 'my awesome avatar')
.attach('avatar', 'test/fixtures/homeboy.jpg')
...

每次都传入一个appurl是不必要的,如果你的测试相同的主机名(域名)时,可以简单地重新初始化请求路径即可,然后一个新的测试实例会在每一个request.VERB()前创建:

request = request('http://localhost:5555');
 
request.get('/').expect(200, function(err){
  console.log(err);
});
 
request.get('/').expect('heya', function(err){
  console.log(err);
});

在HTTP中,总会使用cookie来保持会话状态。下面是一个在Mocha框架中使用cookie的示例:

var request = require('supertest')
   , should = require('should')
   , express = require('express');
 
 
describe('request.agent(app)', function(){
  var app = express();
  app.use(express.cookieParser());
 
  app.get('/', function(req, res){
    res.cookie('cookie', 'hey');
    res.send();
  });
 
  app.get('/return', function(req, res){
    if (req.cookies.cookie) res.send(req.cookies.cookie);
    else res.send(':(')
  });
 
  var agent = request.agent(app);
 
  it('should save cookies', function(done){
    agent
    .get('/')
    .expect('set-cookie', 'cookie=hey; Path=/', done);
  })
 
  it('should send cookies', function(done){
    agent
    .get('/return')
    .expect('hey', done);
  })
})


3. API

supertest基于super-agent构建。在测试时,我们可以使用这个模块的一些底层的API。

  • .expect(status[, fn])-断言一个HTTP响应状态码
  • .expect(status, body[, fn])-断言一个HTTP响应状态码及响应体
  • .expect(body[, fn])-断言HTTP响应体(字符串、正则表达式或对象)
  • .expect(field, value[, fn])-断言HTTP头中的字段名与字段值(字符串、正则表达式)
  • .expect(function(res) {})-使用自定义的断言函数,它会对响应对象进行检查。
    request(app)
      .get('/')
      .expect(hasPreviousAndNextKeys)
      .end(done);
     
    function hasPreviousAndNextKeys(res) {
      if (!('next' in res.body)) return "missing next key";
      if (!('prev' in res.body)) throw new Error("missing prev key");
    }
  • .end(fn)-断言一个HTTP响应状态码
  • .expect(status[, fn])-执行请求并调用回调函数fn(err, res)