Node.js单元测试 - 使用mocha创建模拟层

时间:2016-02-12 10:47:07

标签: node.js unit-testing mocha

在执行一些验证和数据操作(普通业务逻辑)之后,我编写了一个确实使用外部Web服务的Web服务。我需要编写相同的单元测试,并且还需要有代码覆盖率报告。网上有很多建议,摩卡是最重要的。但是在所有可用的示例中,实际的DB调用或外部服务调用都会发生。我的要求是不要进行实际的外部服务调用,而只是模拟调用(就像我们在Java中使用EasyMock一样)。任何帮助将受到高度赞赏。是否可以在节点js中创建DB调用或外部服务调用的模拟?

1 个答案:

答案 0 :(得分:0)

您可以将Sinon与Mocha一起使用来提供存根或间谍调用。同样重要的是还要编写代码以帮助模拟。例如,不要假设Web组件中存在数据库处理程序,通过构造函数传递它。这样就很容易进行测试,用你自己的“模拟”版本替换数据库。

作为示例 - 这是我的一组测试的开始,我将一个模拟的连接池实例化到我的数据库处理程序并将其传递给测试。我实际上也在嘲笑Web服务器,只是测试API。

(function(){
  'use strict';

  const DBHOST = 'dummy';
  const DBNAME = 'dummy';


  const expect = require('chai').expect;
  const sinon = require('sinon');


  const mock = require('../mock/server');
  const DB = require('../database');
  const Logging = require('../log');
  Logging.debug(true); //set to log debug message
  const logger = Logging.logger;
  const poolPromise = mock.getPool();
  const db = new DB(mock.Pool,DBNAME,logger);

  const API = require('../api');
  const api = new API(mock.server,db,logger);




  describe('API tests',function() {
    let sandbox, testConnection;
    beforeEach(function(){
      sandbox = sinon.sandbox.create();
      testConnection = new mock.Connection();
      return poolPromise.then(pool => {
        pool.getConnection().then(cb => {
          cb(null,testConnection);
        });
      });

    });
    afterEach(function(){
      sandbox.restore();
    });

    describe('/logon',function() {
      let params;
      describe('Admin', function() {
        beforeEach(function() {
          params = {name: 'Admin', password: 'abcde'};
        })
        it('Performs logon if username is "Admin" and password is good', function(done) {
          mock.server.emit('/logon', params, (status,user) => {
            expect(status).to.be.true;
            expect(user).to.be.an('object');
            expect(user.uid).to.be.equal(0);
            expect(user.name).to.be.equal('Super User');
            expect(user.keys).to.be.equal('A');
            done();
          });
          testConnection.next.then(value => {
            let request = value.request;
            expect(value.name).to.equal('execSql');
            expect(request.sqlTextOrProcedure).to.equal('SELECT passwordsalt FROM Admin WHERE AdminID = 0');
            request.emit('row', mock.makeRow('passwordsalt',['salt']));
            request.callback(null,1);
            return testConnection.next;
          }).then(value => {
            let request = value.request
            expect(value.name).to.equal('callProcedure');
            expect(request.sqlTextOrProcedure).to.equal('CheckPassword');
            request.emit('row',mock.makeRow('a',[1]));
            request.callback(null,0);
          });
        });