Wade Xu

-- 拓展测试的边界
posts - 25, comments - 181, trackbacks - 0, articles - 0

导航

公告

带你入门带你飞Ⅱ 使用Mocha + Chai + SuperTest测试Restful API in node.js

Posted on 2015-07-28 09:56 WadeXu 阅读(...) 评论(...) 编辑 收藏

目录
  1. 简介
  2. 准备开始
  3. Restful API测试实战
      Example 1 - GET
      Example 2 - Post
      Example 3 - Put
      Example 4 - Delete
  4. Troubleshooting
  5. 参考文档

 

简介

经过上一篇文章的介绍,相信你已经对mocha, chai有一定的了解了, 本篇主要讲述如何用supertest来测试nodejs项目中的Restful API, 项目基于express框架。

SuperTest 是 SuperAgent一个扩展, 一个轻量级 HTTP AJAX 请求库.

SuperTest provides high-level abstractions for testing node.js API endpoint responses with easy to understand assertions.

 

准备开始

npm安装命令

npm install supertest

 

nodejs项目文件目录结构如下

 

├── config
│   └── config.json
├── controllers
│   └── dashboard
│       └── widgets
│           └── index.js
├── models
│   └── widgets.js
├── lib
│   └── jdbc.js
├── package.json
└── test
    └── controllers
        └── dashboard
            └── widgets
                └── index_IntegrationTest.js 

测试代码写在index_IntegrationTest.js这个文件中

 

Restful API测试实战

测试依赖库

var express = require('express');
var kraken = require('kraken-js');
var request = require('supertest');
var chai = require('chai');
var assert = chai.assert;

##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html 

 

Example 1 - GET

Controller/dashboard/widgets/index.js

var _widgets = require('../../../models/widgets.js');

module.exports = function(router) {

  router.get('/', function(req, res) {
    _widgets.getWidgets(req.user.id)
            .then(function(widgets){
              return res.json(widgets);
            })
            .catch(function(err){
              return res.json ({
                code: '000-0001',
                message: 'failed to get widgets:'+err
              });
            });
  });
};

 

测试代码:

var kraken = require('kraken-js');
var express = require('express');
var request = require('supertest');
var aweb = require('acxiom-web');
var chance = new(require('chance'))();
var chai = require('chai');
var assert = chai.assert;

describe('/dashboard/widgets', function() {

  var app, mock;

  before(function(done) {
    app = express();
    app.on('start', done);

    app.use(kraken({
      basedir: process.cwd(),
      onconfig: function(config, next) {
        //some config info

        next(null, config);
      }
    }));

    mock = app.listen(1337);

  });

  after(function(done) {
    mock.close(done);
  });

  it('get widgets', function(done) {
    request(mock)
      .get('/dashboard/widgets/')
      .set('Accept', 'application/json')
      .expect(200)
      .expect('Content-Type', 'application/json; charset=utf-8')
      .end(function(err, res) {
        if (err) return done(err);
        assert.isArray(res.body, 'return widgets object');
        done();
      });
  });

});

 

Example 2 - Post

被测代码:

  router.post('/', function(req, res) {
    _widgets.addWidget(req.user.id, req.body.widget)
            .then(function(widget){
              return res.json(widget);
            })
            .catch(function(err){
              return res.json ({
                code: '000-0002',
                message: 'failed to add widget:' + err
              });
            });
  });

 

测试代码:

  it('add widgets', function(done) {
   var body = {
    widget: {
    type: 'billing',
    color: 'blue',
    location: {
        x: '1',
        y: '5'
      }
     }
    };

    request(mock)
      .post('/dashboard/widgets/')
      .send(body)
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function(err, res) {
        if (err) return done(err);
        assert.equal(res.body.type, 'billing');
        assert.equal(res.body.color, 'blue');
        done();
      });
  });

##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html 

 

Example 3 - Put

被测代码

  router.put('/color/:id', function(req, res) {
    _widgets.changeWidgetColor(req.params.id, req.body.color)
            .then(function(status){
              return res.json(status);
            })
            .catch(function(err){
              return res.json ({
                code: '000-0004',
                message: 'failed to change widget color:' + err
              });
            });
  });

 

测试代码

  describe('change widget color', function() {
    var id = '';
    before(function(done) {
      var body = {
        widget: {
          type: 'billing',
          color: 'blue',
          location: {
            x: '1',
            y: '5'
          }
        }
      };

      request(mock)
        .post('/dashboard/widgets/')
        .send(body)
        .expect(200)
        .expect('Content-Type', /json/)
        .end(function(err, res) {
          if (err) return done(err);
          id = res.body.id;
          done();
        });

    });

    it('change widget color to white', function(done) {
      var body = {
        color: 'white'
      };

      request(mock)
        .put('/dashboard/widgets/color/' + id)
        .send(body)
        .expect(200)
        .expect({
          status: 'success'
        })
        .expect('Content-Type', /json/)
        .end(function(err, res) {
          if (err) return done(err);
          done();
        });
    });
  });

在这个测试case中,前提是要先create 一个widget, 拿到id之后你才可以针对这个刚创建的widget修改, 所以在it之前用了 before 做数据准备。

 

Example 4 - Delete

被测代码

  router.delete('/:id', function(req, res) {
    _widgets.deleteWidget(req.user.id, req.params.id)
            .then(function(status){
              return res.json(status);
            })
            .catch(function(err){
              return res.json ({
                code: '000-0003',
                message: 'failed to delete widget:' + err
              });
            });
  });

 

测试代码

  describe('delete widget', function() {
    var id = '';
    before(function(done) {
      var body = {
        widget: {
          type: 'billing',
          color: 'blue',
          location: {
            x: '1',
            y: '5'
          }
        }
      };

      request(mock)
        .post('/dashboard/widgets/')
        .send(body)
        .expect(200)
        .expect('Content-Type', /json/)
        .end(function(err, res) {
          if (err) return done(err);
          id = res.body.id;
          done();
        });

    });

    it('delete a specific widget', function(done) {
      request(mock)
        .del('/dashboard/widgets/' + id)
        .expect(200)
        .expect('Content-Type', /json/)
        .end(function(err, res) {
          if (err) return done(err);
          assert.deepEqual(res.body, {
            status: 'success'
          });
          done();
        });
    });
  });

注意这里用的是del 不是 delete, Supertest提供的delete方法是del, 不是delete

 

##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html 

 

测试结果如下:

 

Troubleshooting

 1. 当你用request().delete() 时报错TypeError: undefined is not a function

换成request().del()

  

参考文档

Mocha: http://mochajs.org/

Chai: http://chaijs.com/

SuperTest: https://www.npmjs.com/package/supertest

 

感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。

##转载注明出处:http://www.cnblogs.com/wade-xu/p/4673460.html