How to mock dependency classes for unit testing with mocha.js?

33,456

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.

Share:
33,456

Related videos on Youtube

mvmoay
Author by

mvmoay

Developing web applications with PHP and Vue.js

Updated on January 14, 2021

Comments

  • mvmoay
    mvmoay over 3 years

    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???
        });
    });
    
    • Mritunjay
      Mritunjay almost 9 years
      read about DI
  • mvmoay
    mvmoay almost 9 years
    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?
  • victorkt
    victorkt almost 9 years
    Check this answer I gave a few days ago stackoverflow.com/questions/32550115/…
  • Willwsharp
    Willwsharp over 6 years
    How would you do this for the constructor of B?
  • EmandM
    EmandM about 6 years
    ts-mock-imports Is a library I created that allows you to mock out a class import without running the class constructor.
  • nicoramirezdev
    nicoramirezdev over 3 years
    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
  • zumalifeguard
    zumalifeguard about 2 years
    That link is now bad. Use this: sinonjs.org/releases/latest/stubs