使用 mockery 和 sinon 模拟 class 方法

Mock a class method using mockery and sinon

我正在学习使用 sinon 的节点模块模拟进行单元测试。

仅使用嘲弄和普通 class 我能够成功注入模拟。但是我想注入一个 sinon 存根而不是普通的 class 但是我遇到了很多麻烦。

我要模拟的class:

function LdapAuth(options) {}

// The function that I want to mock.
LdapAuth.prototype.authenticate = function (username, password, callback) {}

这是我目前在 beforeEach() 函数中使用的代码:

    beforeEach(function() {
        ldapAuthMock = sinon.stub(LdapAuth.prototype, "authenticate", function(username, password, callback) {});
        mockery.registerMock('ldapauth-fork', ldapAuthMock);
        mockery.enable();
    });

    afterEach(function () {
        ldapAuthMock.restore();
        mockery.disable();
    });

我试过 mock/stub LdapAuth class 以各种方式没有成功,上面的代码只是最新版本,不起作用。

所以我只想知道如何使用 sinon 和 mockery 成功模拟它。

由于 Node 的模块缓存、Javascript 的动态特性和原型继承,这些节点模拟库可能非常麻烦。

幸运的是,Sinon 还负责修改您尝试模拟的对象,并提供一个很好的 API 来构建间谍、潜艇和模拟。

这是我如何对 authenticate 方法进行存根的小示例:

// ldap-auth.js

function LdapAuth(options) {
}

LdapAuth.prototype.authenticate = function (username, password, callback) {
  callback(null, 'original');
}

module.exports = LdapAuth;
// test.js

var sinon = require('sinon');
var assert = require('assert');
var LdapAuth = require('./ldap-auth');

describe('LdapAuth#authenticate(..)', function () {
  beforeEach(function() {
    this.authenticateStub = sinon
                              // Replace the authenticate function
                              .stub(LdapAuth.prototype, 'authenticate')
                              // Make it invoke the callback with (null, 'stub')
                              .yields(null, 'stub');
  });

  it('should invoke the stubbed function', function (done) {
    var ldap = new LdapAuth();
    ldap.authenticate('user', 'pass', function (error, value) {
      assert.ifError(error);
      // Make sure the "returned" value is from our stub function
      assert.equal(value, 'stub');
      // Call done because we are testing an asynchronous function
      done();
    });
    // You can also use some of Sinon's functions to verify that the stub was in fact invoked
    assert(this.authenticateStub.calledWith('user', 'pass'));
  });

  afterEach(function () {
    this.authenticateStub.restore();
  });
});

希望对您有所帮助。