How to stub IIFE module - javascript

I am running Node v16.11.0. Trying to test a Worker module that I defined as such:
const Worker = (function(){
function start(){...}
function stop(){...}
function privateFunction1(){
...some stuff
...calls privateFunction2();
}
function privateFunction2(){...}
return {
start: start,
stop: stop,
/** for testing only:**/
_privateFunction1: privateFunction1,
_privateFunction2: privateFunction2
}
})();
module.exports = Worker;
And in my test file I have:
const worker = require("../../worker");
const sinon = require("sinon");
const chai = require("chai");
var assert = chai.assert;
var expect = chai.expect;
describe("Worker", function () {
const sandbox = sinon.createSandbox();
describe("#privateFunction1", function () {
.....
beforeEach(function () {
removeStub = sandbox.stub(worker, "_privateFunction2");
.......
});
afterEach(function () {
sandbox.restore();
});
it("should test something", function () {
let obj = {} //just for demo purposes
assert.equal(worker._privateFunction1(obj), false);
});
The expectation here is that _privateFunction1() will start executing, will call the privateFunction2 and that call will be handled by the stub.
But the real method gets called instead. Stubbing doesn't work.
Anyone has any ideas what is missing here?
Thanks

Related

jest mock a property that is an object and a function at the same time

I am trying to mock a property of an object that acts as an object and as a function at the same time. Here's the code:
index.js
const nock = require('nock');
async function myFunc() {
nock.back.setMode('param1');
const { nockDone } = await nock.back('param1', 'param2');
nock.enableNetConnect('param1');
return nockDone;
}
module.exports = { myFunc }
My goal is to mock the nock object in a way I can assert that when myFunc is called, nock.back is called with param1 and param2.
To do so I have the following test:
index.test.js
const nock = require('nock');
const subjectUnderTest = require('./index');
const nockBackImplementation = jest.fn();
nockBackImplementation.setMode = jest.fn();
const nockBackMock = jest.spyOn(nock, 'back');
nockBackMock.mockImplementation(() => nockBackImplementation);
describe('test', () => {
it('calls nock.back with the proper parameters', () => {
subjectUnderTest.myFunc();
expect(nockBackMock).toHaveBeenCalledWith('param1', 'param2');
});
});
For some reason, the test fails saying that the mock function has not been called and also gives this error:
UnhandledPromiseRejectionWarning: TypeError: nock.back.setMode is not a function
I'm not sure how to properly mock nock.
You're assigning the setMode mock to the function used as implementation, which I think is different from the actual nock.back mock. You can set it correctly this way
const nockBackMock = jest
.spyOn(nock, "back")
.mockResolvedValue({ nockDone: "test" });
nockBackMock.setMode = jest.fn();
// you also need to mock the enableNetConnect to avoid errors
const enableNetConnectMock = jest
.spyOn(nock, "enableNetConnect")
.mockReturnValue({});
describe("test", () => {
it("calls nock.back with the proper parameters", () => {
subjectUnderTest.myFunc();
expect(nockBackMock).toHaveBeenCalledWith("param1", "param2");
});
});

How to (sinon) stub an external module function?

import fileType from 'file-type';
export function checkFileType(input){
if(fileType(input).mime === 'image/png'){
// do something;
return 'Yes It is PNG';
} else {
// do something;
return 'No. It is not PNG';
}
}
I want to write unit test case for the above method, in that I want to stub 'fileType(input)'.
I have tried to do like below in my test file.
import * as fileTypeObj from 'file-type';
import sinon from 'sinon';
describe(__filename, () => {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
});
afterEach(() => {
sandbox.restore();
});
it('test the function', async () => {
sandbox.stub(fileTypeObj, 'default').withArgs('someinput').returns({mime: 'image/png'});
await checkFileType('someinput)';
})
})
But it is not working as expected (Not stubbing ... making the direct actual call).
Please help me to stub properly and test.
file-type package export function as default, so it is a bit harder to mock with just Sinon. We must involve proxyquire to make the testing easier.
This is how the test looks like using proxyquire
const chai = require('chai');
const sinon = require('sinon');
const proxyquire = require('proxyquire');
const expect = chai.expect;
describe('unit test', function() {
let fileTypeStub;
let src;
beforeEach(function() {
fileTypeStub = sinon.stub();
src = proxyquire('./path-to-your-src', { 'file-type': fileTypeStub });
});
afterEach(function() {
sinon.restore();
})
it('returns yes for PNG', async function() {
fileTypeStub.returns({ mime: 'image/png'});
const response = await src.checkFileType('any input');
expect(response).to.equal('Yes It is PNG')
});
it('returns no for not PNG', async function() {
fileTypeStub.returns({ mime: 'image/jpg'});
const response = await src.checkFileType('any input');
expect(response).to.equal('No. It is not PNG')
});
});
Hope it helps

How can I stub internally referenced functions with sinonjs?

I have a myModule Node.js module containing:
function b() {
console.log('original b');
}
function a() {
b();
}
exports.a = a
exports.b = b;
And the following test suite using mocha + sinon.js:
const myModule = require('./myModule.js');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
chai.use(sinonChai);
describe('not working stub', () => {
it('should call the stub', () => {
let stub = sinon.stub(myModule, 'b', () => { console.log('stubbed b')});
myModule.a();
expect(stub).to.have.been.called;
})
});
I am expecting the stub to be called, but the original b get called instead, why ?
var stub = sinon.stub(object, "method", func);
This has been removed from v3.0.0. Instead you should use
stub(object, 'method').callsFake(fn).
Or you could use .yields(fn)
https://sinonjs.org/releases/latest/stubs/

Testing for method calls using sinon on module.exports methods

I'm trying to test if a specific method is called given certain conditions using mocha, chai and sinon. Here is the code:
function foo(in, opt) {
if(opt) { bar(); }
else { foobar(); }
}
function bar() {...}
function foobar() {...}
module.exports = {
foo: foo,
bar: bar,
foobar:foobar
};
Here is the code in my test file:
var x = require('./foo'),
sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect,
should = chai.should(),
assert = require('assert');
describe('test 1', function () {
it('should call bar', function () {
var spy = sinon. spy(x.bar);
x.foo('bla', true);
spy.called.should.be.true;
});
});
When I do a console.log on the spy it says it wasn't called even thou with manual logging in the bar method I'm able to see it gets called. Any suggestions on what I might be doing wrong or how to go about it?
Thanks
You've created a spy, but the test code doesn't use it. Replace the original x.bar with your spy (don't forget to do cleanup!)
describe('test 1', function () {
before(() => {
let spy = sinon.spy(x.bar);
x.originalBar = x.bar; // save the original so that we can restore it later.
x.bar = spy; // this is where the magic happens!
});
it('should call bar', function () {
x.foo('bla', true);
x.bar.called.should.be.true; // x.bar is the spy!
});
after(() => {
x.bar = x.originalBar; // clean up!
});
});

Mocking JavaScript constructor with Sinon.JS

I'd like to unit test the following ES6 class:
// service.js
const InternalService = require('internal-service');
class Service {
constructor(args) {
this.internalService = new InternalService(args);
}
getData(args) {
let events = this.internalService.getEvents(args);
let data = getDataFromEvents(events);
return data;
}
}
function getDataFromEvents(events) {...}
module.exports = Service;
How do I mock constructor with Sinon.JS in order to mock getEvents of internalService to test getData?
I looked at Javascript: Mocking Constructor using Sinon but wasn't able to extract a solution.
// test.js
const chai = require('chai');
const sinon = require('sinon');
const should = chai.should();
let Service = require('service');
describe('Service', function() {
it('getData', function() {
// throws: TypeError: Attempted to wrap undefined property Service as function
sinon.stub(Service, 'Service').returns(0);
});
});
You can either create a namespace or create a stub instance using sinon.createStubInstance (this will not invoke the constructor).
Creating a namespace:
const namespace = {
Service: require('./service')
};
describe('Service', function() {
it('getData', function() {
sinon.stub(namespace, 'Service').returns(0);
console.log(new namespace.Service()); // Service {}
});
});
Creating a stub instance:
let Service = require('./service');
describe('Service', function() {
it('getData', function() {
let stub = sinon.createStubInstance(Service);
console.log(stub); // Service {}
});
});

Categories