50

Given that I have two ES6 classes.

This is class A:

import B from 'B';

class A {
    someFunction(){
        var dependency = new B();
        dependency.doSomething();
    }
}

And class B:

class B{
    doSomething(){
        // does something
    }
}

I am unit testing using mocha (with babel for ES6), chai and sinon, which works really great. But how can I provide a mock class for class B when testing class A?

I want to mock the entire class B (or the needed function, doesn't actually matter) so that class A doesn't execute real code but I can provide testing functionality.

This is, what the mocha test looks like for now:

var A = require('path/to/A.js');

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        InstanceOfA.someFunction();
        // How to test A.someFunction() without relying on B???
    });
});
1
  • read about DI Commented Sep 21, 2015 at 12:31

1 Answer 1

49

You can use SinonJS to create a stub to prevent the real function to be executed.

For example, given class A:

import B from './b';

class A {
    someFunction(){
        var dependency = new B();
        return dependency.doSomething();
    }
}

export default A;

And class B:

class B {
    doSomething(){
        return 'real';
    }
}

export default B;

The test could look like: (sinon < v3.0.0)

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        sinon.stub(B.prototype, 'doSomething', () => 'mock');
        let res = InstanceOfA.someFunction();

        sinon.assert.calledOnce(B.prototype.doSomething);
        res.should.equal('mock');
    });
});

EDIT: for sinon versions >= v3.0.0, use this:

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        sinon.stub(B.prototype, 'doSomething').callsFake(() => 'mock');
        let res = InstanceOfA.someFunction();

        sinon.assert.calledOnce(B.prototype.doSomething);
        res.should.equal('mock');
    });
});

You can then restore the function if necessary using object.method.restore();:

var stub = sinon.stub(object, "method");
Replaces object.method with a stub function. The original function can be restored by calling object.method.restore(); (or stub.restore();). An exception is thrown if the property is not already a function, to help avoid typos when stubbing methods.

Sign up to request clarification or add additional context in comments.

6 Comments

Woa. That easy. Didn't think of altering the prototype. Thanks! :) Do you have a tip on how to mock the constructor? Seems not to work the same way?
Check this answer I gave a few days ago stackoverflow.com/questions/32550115/…
How would you do this for the constructor of B?
ts-mock-imports Is a library I created that allows you to mock out a class import without running the class constructor.
This seems to be deprecated github.com/sinonjs/sinon/issues/1761 The right aproach is on this docs sinonjs.org/releases/v5.0.3/stubs
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.