Search code examples
javascriptnode.jsjasminefrontendjasmine-node

How to spy on a method inside a dependent module using jasmine-node


I am trying to write jasmine tests for a module-(say moduleA) which 'requires' another module-(moduleB).

======> moduleB.js

function moduleBFunction(){
   console.log('function inside moduleB is called');
}

======> moduleA.js

var moduleB = require('./moduleB');
function moduleAfunction(input){
   if(input){
      moduleB.moduleBFunction()
   }

}

I want to write a jasmine test case that tests when i call moduleAfunction, is it calling moduleBfunction or not. I tried to write a test using spyOn(). but i am not sure how can i mock a method inside a dependent module. I did some research and found i might be able to use 'rewire' module for this purpose like below

var moduleB = require('../moduleB');
moduleB.__set__('moduleBfunction', moduleBfunctionSpy);
moduleA.__set__('moduleB', moduleB);
it('should call moduleBfunction', function(){
    moduleA.moduleAfunction()
    expect(moduleB.moduleBfunction()).toHaveBeenCalled()
});

but I feel there should be a simpler way.

Please suggest.


Solution

  • I recommend sinon.js

    var sinon = require('sinon')
    var moduleA = require('../moduleA')
    var moduleB = require('../moduleB')
    
    
    it('should call moduleBfunction', function() {
      var stub = sinon.stub(moduleB, 'moduleBfunction').returns()
      moduleA.moduleAfunction()
      expect(moduleB.moduleBfunction.calledOnce)
      stub.restore()
    })
    

    You can easily fake many different behaviours like:

    • stub throws
    • stub returns a certain value
    • stub yields (mimicking async callback)
    • stub works restricted with just for certain input arguments

    Don't forget to restore each stub before executing the next test. It's best to use sandboxes and afterEach / beforeEach

    describe('tests which require some fakes', function() {
      var sandbox
    
      beforeEach(function() {
        sandbox = sinon.sandbox.create()
      })
    
      afterEach(function() {
        sandbox.restore()
      })
    })