Search code examples
javascriptunit-testingsinonfunction-expression

Sinon spy on function expression


is it possible to make sinon spy on function expressions? Look this code for example.

function one() { return 1; }
function two() { return 2; }
function three() { return 3; }

function myMethod() {
  var n1 = one();
  var n2 = two();
  var n3 = three();
  return n1 + n2 + n3;
}


QUnit.module('My test');

QUnit.test('testing functions', (assert) => {
  assert.expect(3);
  
  const spyOne = sinon.spy(one);
  const spyTwo = sinon.spy(two);
  const spyThree = sinon.spy(three);
	myMethod();

  assert.ok(spyOne.called, "called one");
  assert.ok(spyTwo.called, "called two");
  assert.ok(spyThree.called, "called three");
  
  sinon.restore();
});

Even though I call myMethod() and I have spies on one - two - three I still get false on one.called (same for two and three)

What am I missing here?

Thanks!


Solution

  • Calling sinon.spy(fn) doesn't change fn, it merely creates a new function (the spy) that will call fn.

    For you to be able to test one, two, three, you need to replace those functions (or rather, their references) with spies, and restore them afterwards:

    // keep references to the original functions
    var _one   = one;
    var _two   = two;
    var _three = three;
    
    // replace the original functions with spies
    one   = sinon.spy(one);
    two   = sinon.spy(two);
    three = sinon.spy(three);
    
    // call our method
    myMethod();
    
    // test
    assert.ok(one.called,   "called one");
    assert.ok(two.called,   "called two");
    assert.ok(three.called, "called three");
    
    // restore the original functions
    one   = _one;
    two   = _two;
    three = _three;
    

    It's not ideal though, and if possible I would probably group all the functions into an object. That would also enable Sinon to restore the originals itself.