Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Mocking Constructor using Sinon

I am pulling my hair out trying to figure out how to mock a constructor using sinon. I have a function that will create multiple widgets by calling a constructor that accepts a few arguments. I want to verify that the constructor is called the correct number of times with the correct parameters, but I don't want to actually construct the widgets. The following links seemingly explain a straightforward way of mocking the constructor, however it does not work for me:

Spying on a constructor using Jasmine

http://tinnedfruit.com/2011/03/25/testing-backbone-apps-with-jasmine-sinon-2.html

When I make the following call to stub the constructor:

sinon.stub(window, "MyWidget");

I get the following error:

Uncaught TypeError: Attempted to wrap undefined property MyWidget as function 

When debugging in Chrome I see MyWidget shows up in the Local section of the Scope Variables, however there is not MyWidget property off of window.

Any help would be greatly appreciated.

like image 466
sevenstripe Avatar asked Jan 28 '13 19:01

sevenstripe


People also ask

How do you mock a constructor in JavaScript?

In order to mock a constructor function, the module factory must return a constructor function. In other words, the module factory must be a function that returns a function - a higher-order function (HOF). Since calls to jest. mock() are hoisted to the top of the file, Jest prevents access to out-of-scope variables.

How do you mock a function in Sinon?

Mocks allow you to create a fake function that passes or fails depending on your needs. You can ensure it was called with certain arguments, or check how many times it was called. You must call mock() on an object.

How do you mock a variable in Sinon?

var sinon = require('sinon'); var start_end = require('./start_end'); describe("start_end", function(){ before(function () { cb_spy = sinon. spy(); }); afterEach(function () { cb_spy. reset(); }); it("start_pool()", function(done){ // how to make timer variable < 1, so that if(timer < 1) will meet start_end.


2 Answers

I needed a solution for this because my code was calling the new operator. I wanted to mock the object that the new call created.

var MockExample = sinon.stub();
MockExample.prototype.test = sinon.stub().returns("42");
var example = new MockExample();
console.log("example: " + example.test()); // outputs 42

Then I used rewire to inject it into the code that I was testing

rewiredModule = rewire('/path/to/module.js');
rewiredModule.__set__("Example", example);
like image 158
starmer Avatar answered Oct 16 '22 18:10

starmer


From the official site of sinonjs:

Replaces object.method with a stub function. The original function can be restored bycalling 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.

this simply states that the function for which you want to create the stub must be member of the object object.

To make things clear; you call

sinon.stub(window, "MyWidget");

The MyWidget function needs to be within the global scope (since you pass window as parameter). However, as you already said, this function is in a local scope (probably defined within an object literal or a namespace).

In javascript everyone can have access to the global scope, but not the other way around.

Check where you declare the MyWidget function and pass container object as first parameter to sinon.stub()

like image 8
ppoliani Avatar answered Oct 16 '22 17:10

ppoliani