Sinon spy does not get called - javascript

The test is failing on the first expectation. Is there a way to inject a spy to a function so that I can check if the function was called with correct arguments?
var myObj = {}
myObj.prop = function propFn () {
return 'foo'
}
myObj.func = function (disp) {
return disp(this.prop())
}
let disp = sinon.spy()
sinon.stub(myObj, 'prop').callsFake(function fakeFn () {
return 'bar'
})
expect(disp.called).to.be.true
disp.should.have.been.calledWith('bar')
Thanks!

Please try as below,
describe('prop', () => {
const myObj = {};
myObj.prop = function propFn() {
return 'foo';
};
myObj.func = function (disp) {
return disp(this.prop());
};
it('should be called', () => {
sinon.stub(myObj, 'prop').returns('bar');
const disp = sinon.spy();
myObj.func(disp);
expect(disp.callCount).to.equal(1);
expect(myObj.prop.callCount).to.equal(1);
expect(disp.callCount).to.equal(1);
expect(disp.calledWith('bar')).to.equal(true);
});
});
result
prop
✓ should be called
1 passing (975ms)

Related

jest.spyOn is not working when called from a side effect call

I have the following scenario:
const doSomething = () => {
const test = 1;
doAnotherThing();
return test + 1;
};
const doAnotherThing = () => {};
module.exports = {
doSomething,
doAnotherThing
};
And here is my test:
const MyModule = require('./myModule');
describe('MyModule', () => {
it('Should be able to spy another call', () => {
const spy = jest.spyOn(MyModule, 'doAnotherThing');
MyModule.doSomething();
expect(spy).toHaveBeenCalledTimes(1);
});
});
Question, is there a way for the call doAnotherThing() inside the doSomething() be spied by jest in some way, without using solutions like rewire?
Found the solution here: https://medium.com/welldone-software/jest-how-to-mock-a-function-call-inside-a-module-21c05c57a39f
Redefined my module to this and now it's working
const doSomething = () => {
const test = 1;
MyModule.doAnotherThing();
return test + 1;
};
const doAnotherThing = () => {};
const MyModule = {
doSomething: doSomething,
doAnotherThing: doAnotherThing
};
export default MyModule;

Testing nested function in Jest

I have in file.js code which I simplify this way:
function Apple(,data) {
this.attr1 = data.attr1,
this.attr2 = data.attr2,
this.doSomething(data.flag);
}
Apple.prototype = new function() {
this.function1 = function() {
// do something
}
this.doSomething = function(flag) {
// return value
}
}
I want to test function1(), for that, I want to mock first doSomething() to return a specific value, but I am failing because any call to Apple() function executes immediately doSomething():
describe('Apple', () => {
test('test function1()', () => {
Apple.doSomething = jest.fn().mockImplementation((2) => {
// do something;
});
let apple = new Apple(data); // the original doSomething() executes here instead of the mocked version
});
});
How can I achieve my goal ?
Try using spyOn:
const mockDoSomething = jest.spyOn(Apple.prototype, 'doSomething').mockReturnValueOnce((flag) => {
// mock do something;
})

How to make a nested function call within an IIFE?

const parkReport = () => {
return {
averageAge: () => {
return console.log('Something');
}
}
};
const initialize = ( parkReport => {
return parkReport.averageAge();
})(parkReport);
In the IIFE initialize parkReport.averageAge() is showing an error of not a function. How do you call the nested AverageAge() from initialize?
You need to call the parkReport function. Here you are passing parkReport as a callback to the IIFE. so you need to call it to expect something returned from it.
const parkReport = () => {
return {
averageAge: () => {
return console.log('Something');
}
}
};
const initialize = (parkReport => {
return parkReport() // call it
.averageAge(); // and get the age
})(parkReport);

Stubs and proxquire

I'm having an issue with stubbing a particular function with sinon after having used proxyquire.
Example:
// a.js
const api = require('api');
module.exports = (function () {
return {
run,
doStuff
};
function run() {
return api()
.then((data) => {
return doStuff(data);
})
}
function doStuff(data) {
return `Got data: ${data}`;
}
})()
// a.spec.js - in the test
a = proxyquire('./a', {
'api': () => Promise.resolve('data')
})
sinon.stub(a, 'doStuff');
// RUN TEST - call a.run()
I know it isn't working because it calls the original doStuff instead of a mocked/stubbed doStuff.
I know it isn't working because it calls the original doStuff instead
of a mocked/stubbed doStuff.
That is because function run() in a.js invokes function doStuff(data) inside the closure function run() is holding over the content of a.js and not function doStuff(data) in a_spec.js.
Illustration by example
Lets re-write a.js to:
var a = 'I am exported';
var b = 'I am not exported';
function foo () {
console.log(a);
console.log(this.b)
}
module.exports.a=a;
module.exports.foo=foo;
and a.spec.js to:
var one = require('./one');
console.log(one); // { a: 'I am exported', foo: [Function: foo] }
one.a = 'Charles';
one.b = 'Diana';
console.log(one); // { a: 'Charles', foo: [Function: foo], b: 'Diana' }
Now if we invoke one.foo() it will result in:
I am exported
Diana
The I am exported is logged to the console because console.log(a) inside foo points to var a inside the closure foo is holding over the contents of a.js.
The Diana is logged to the console because console.log(this.b) inside foo points to one.b in a.spec.js.
So what do you need to do to make it work?
You need to change:
module.exports = (function () {
return {
run,
doStuff
};
function run() {
return api()
.then((data) => {
return doStuff(data);
})
}
function doStuff(data) {
return `Got data: ${data}`;
}
})()
to:
module.exports = (function () {
return {
run,
doStuff
};
function run() {
return api()
.then((data) => {
return this.doStuff(data); // ´this.doStuff´ points to ´doStuff´ in the exported object
}.bind(this)) // to ensure that ´this´ does not point to the global object
}
function doStuff(data) {
return `Got data: ${data}`;
}
})()

Sinon.spy on a method is not invoked

The code I'm testing is fairly simple: it invokes a method in case a condition is verified. If not, it invokes another method contained within the first one as an attribute.
app.js:
function test (fn, isActivated) {
if (isActivated) {
return fn('foo')
}
return fn.subFn('bar')
}
var fn = function (p) { return p }
fn.subFn = function (p) { return 'sub-' + p }
var resFn = test(fn, true)
var resSubFn = test(fn, false)
document.write(resFn) // shows 'foo' as expected
document.write(resSubFn) // shows 'bar' as expected
I've set a spy on each method but the spy on the fn method does not seem to work while the spy on the contained method subFn works. See below:
app.test.js:
'use strict'
const chai = require('chai')
const sinon = require('sinon')
const trigger = require('../app').trigger
chai.should()
describe('test app', function () {
before(function () {
this.fn = function () {}
this.fn.subFn = function () {}
this.subFnSpy = sinon.spy(this.fn, 'subFn')
this.fnSpy = sinon.spy(this.fn)
})
describe('isActivated is true', function () {
before(function () {
trigger(this.fn, true)
})
it('should invoke fn', function () {
this.fnSpy.callCount.should.equal(1) // return false because callCount = 0
})
})
describe('isActivated is false', function () {
before(function () {
trigger(this.fn, false)
})
it('should invoke subFn', function () {
this.subFnSpy.callCount.should.equal(1) // return false because callCount = 0
})
})
})
Smelling something wrong with the spy on the fn function, I've tried with two separate methods. Both spies fail in this case:
app.js:
exports.trigger = function (fn, subFn, isActivated) {
if (isActivated) {
return fn('fn')
}
return subFn('bar')
}
app.test.js
'use strict'
const chai = require('chai')
const sinon = require('sinon')
const trigger = require('../app').trigger
chai.should()
describe('test app', function () {
before(function () {
this.fn = function () {}
this.subFn = function () {}
this.fnSpy = sinon.spy(this.fn)
this.subFnSpy = sinon.spy(this.subFn)
})
beforeEach(function () {
this.fnSpy.reset()
this.subFnSpy.reset()
})
describe('isActivated is true', function () {
before(function () {
trigger(this.fn, this.subFn, true)
})
it('should invoke fn if isActivated is true', function () {
this.fnSpy.callCount.should.equal(1) // return false
})
})
describe('isActivated is false', function () {
before(function () {
trigger(this.fn, this.subFn, false)
})
it('should invoke subFn if isActivated is true', function () {
this.subFnSpy.callCount.should.equal(1) // return false
})
})
})
Any suggestion of what I'm doing wrong?
I did not find the exact solution but a workaround quite close from one. So the problem seems to lie with the way this.fn is handled withtin sinon.spy, thus instead of doing:
this.fnSpy = sinon.spy(this.fn)
this.subFnSpy = sinon.spy(this.subFn)
We do the following:
this.fnSpy = sinon.spy(this, 'fn')
this.subFnSpy = sinon.spy(this.fn, 'subFn')
The is easd by the fact that I use this to store fn and subFn.

Categories

Resources