Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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???     }); }); 
like image 852
mvmoay Avatar asked Sep 21 '15 12:09

mvmoay


People also ask

When mocking a dependency a dummy class is provided?

Typically when mocking a dependency, a dummy class is provided with many of the same methods as the original. These methods do not provide functionality, but they may just return predictable values that we can use for testing purposes.

When should you mock a dependency?

If the dependency does not depend on anything persistent or external, the only benefit you gain from mocking it is that the test will work properly even if the dependency is wrong - but that's assuming the mock works properly. For that you need to either: Write a mock that emulates the dependency completely.

Is mocking a dependency injection?

Dependency injection is a way to scale the mocking approach. If a lot of use cases are relying on the interaction you'd like to mock, then it makes sense to invest in dependency injection. Systems that lend themselves easily to dependency injection: An authentication/authorization service.


1 Answers

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.

like image 96
victorkt Avatar answered Oct 11 '22 08:10

victorkt