Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock a class method using mockery and sinon

I'm learning to unit test using the node module mockery with sinon.

Using only mockery and a plain class I'm able to inject a mock successfully. However I would like to inject a sinon stub instead of a plain class but I'm having a lot of troubles with this.

The class I am trying to mock:

function LdapAuth(options) {}

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

And here is the code I'm currently using in my beforeEach() function:

    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();
    });

I've tried to mock/stub the LdapAuth class in various ways without success and the code above is just the latest version that doesn't work.

So I just want to know how to mock this successfully using sinon and mockery.

like image 640
grimurd Avatar asked Feb 09 '15 15:02

grimurd


People also ask

How do you mock a method using Sinon?

var mock = sinon. Creates a mock for the provided object. Does not change the object, but returns a mock object to set expectations on the object's methods.

What is Sinon used for?

Sinon JS is a popular JavaScript library that lets you replace complicated parts of your code that are hard to test for “placeholders,” so you can keep your unit tests fast and deterministic, as they should be.

What is Sinon stub ()?

The sinon. stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.

What is a stub vs mock?

Stub: a dummy piece of code that lets the test run, but you don't care what happens to it. Substitutes for real working code. Mock: a dummy piece of code that you verify is called correctly as part of the test. Substitutes for real working code.


1 Answers

These node mocking libraries can be quite cumbersome because of Node's module cache, Javascript's dynamic nature and it's prototypical inheritance.

Fortunately Sinon also takes care of modifying the object you are trying to mock as well as providing a nice API to construct spys, subs and mocks.

Here is a small example of how I would stub the authenticate method:

// 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();
  });
});

I hope this helps.

like image 135
Sveinn Fannar Avatar answered Sep 21 '22 00:09

Sveinn Fannar