'How to sinon spy module export utility functions

In javascript (ES6), I have a utility module which just contains some functions, and then in the end of the file, I export them like so:

module.exports = {
  someFunction1,
  someFunction2,
  someFunction3,
}

Then I want to write unit tests for those functions. Some of the functions depend on each other; they call each other in a way, that for example, someFunction1 might call someFunction2. There's no circular problems.

Everything works well, until I need to spy that one of the functions is called. How can I do it? Currently I'm using Chai and Sinon.

In the test file, I have imported the whole file as a module:

const wholeModule = require('path/to/the/js/file')

And finally, my test looks like following:

it('should call the someFunction2', (done) => {
  const spy = sinon.spy(wholeModule, 'someFunction2')

  wholeModule.someFunction1() // someFunction2 is called inside someFunction1

  assert(spy.calledOnce, 'someFunction2 should be called once')
  done()
})

The problem is, that the test fails, because in someFunction1, the someFunction2 function is used directly. I apply the spy to the module object's function. But that's a different object. Here's an example of the someFunction1:

function someFunction1() {
  someFunction2()
  return 2;
}

I know the reason why it won't work, but I don't know what would be the best practise in this case to make it work? Please help!



Solution 1:[1]

As you are already aware this happens because you are stubbing the exported reference not the actual method in the module. It works in any module that includes the one you are replacing since they include the exported references but when inside the same module it's just calling the local function.

The easiest solution I've found is just to call the reference:

function someFunction1() {
  this.someFunction2()
  return 2;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dan Conway