I have a Module a
const b = require(./b);
function aGetResult() {
return b.getInfo();
}
Module B
const c = require(./c);
function getInfo() {
return getDetailInfo();
}
function getDetailInfo() {
const result = c.getApiResult();
return result
}
Module C
function getApiResult() {
return api.get(/test/1);
}
I've written a test for module A but am running into an issue with stubbing dependencies.I just want to stub c.getApiResult() and not b.getInfo() or b.getDetailInfo(). I've tried selectively stubbing using proxyquire but am having issues. Any help?
You should use Globally override require of proxyquire package.
a depends b, b depends on c. Now you want to mock the indirect c dependency instead of direct b dependency when you test a. It's NOT recommended to do this. But anyway, here is the solution:
E.g.
a.js:
const b = require('./b');
function aGetResult() {
return b.getInfo();
}
exports.aGetResult = aGetResult;
b.js:
const c = require('./c');
function getInfo() {
return getDetailInfo();
}
function getDetailInfo() {
const result = c.getApiResult();
return result;
}
module.exports = { getInfo };
c.js:
const api = {
get(url) {
return 'real result';
},
};
function getApiResult() {
return api.get('/test/1');
}
module.exports = { getApiResult };
a.test.js:
const proxyquire = require('proxyquire');
const { expect } = require('chai');
const sinon = require('sinon');
describe('63275147', () => {
it('should pass', () => {
const stubs = {
'./c': {
getApiResult: sinon.stub().returns('stubbed result'),
'#global': true,
},
};
const a = proxyquire('./a', stubs);
const actual = a.aGetResult();
expect(actual).to.be.eq('stubbed result');
sinon.assert.calledOnce(stubs['./c'].getApiResult);
});
});
unit test result:
63275147
✓ should pass (2630ms)
1 passing (3s)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 83.33 | 100 | 60 | 83.33 |
a.js | 100 | 100 | 100 | 100 |
b.js | 100 | 100 | 100 | 100 |
c.js | 50 | 100 | 0 | 50 | 3-8
----------|---------|----------|---------|---------|-------------------
Related
I am trying to stub a call to the aws parameter store (PS). But even though I added the stub in multiple ways it always makes the actual call to aws PS.
the method I am trying to test
function getParamsFromParamterStore() {
return ssm.getParametersByPath(query).promise();
}
One of the stub method I tried
var ssm = new AWS.SSM();
stub1 = sinon.stub(ssm, 'getParametersByPath').returns({promise: () => {}});
moduleName.__get__('getParamsFromParamterStore')();
But this actually makes the call to PS.
Note: since this is a private function (not exported) I am using rewire to access it.
Here is the unit test solution:
index.js:
const AWS = require('aws-sdk');
const ssm = new AWS.SSM();
function getParamsFromParamterStore(query) {
return ssm.getParametersByPath(query).promise();
}
index.test.js:
const rewire = require('rewire');
const sinon = require('sinon');
const { expect } = require('chai');
const mod = rewire('./');
describe('60447015', () => {
it('should pass', async () => {
const ssmMock = { getParametersByPath: sinon.stub().returnsThis(), promise: sinon.stub().resolves('mock data') };
const awsMock = {
SSM: ssmMock,
};
mod.__set__('ssm', awsMock.SSM);
const actual = await mod.__get__('getParamsFromParamterStore')('query');
expect(actual).to.be.eq('mock data');
sinon.assert.calledWithExactly(ssmMock.getParametersByPath, 'query');
sinon.assert.calledOnce(ssmMock.promise);
});
});
Unit test results with 100% coverage:
60447015
✓ should pass
1 passing (30ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
I'm writing a unit test for a function that uses node-cache.
At the following function,
I want to have a string return at the first cache.get
an array in the second cache.get
Please note that I removed some parts of code from testFunction since it is not relavant to my question.
const NodeCache = require('node-cache');
const cache = new NodeCache();
...
const testFunction = () => {
let myStringCache = cache.get('cacheName1');
let myArrayCache = cache.get('cacheName2');
... Do something with caches ...
return 'return something';
}
...
module.exports = {
...,
testFunction,
...
}
I created the following test
describe('sample test with testFunction() ', ()=>{
let stubCache;
let stub;
before((done)=>{
sandbox = sinon.createSandbox();
stubCache = sandbox.stub(cache, 'get');
stubCache.withArgs('cacheName1').returns('sample string');
stubCache.withArgs('cacheName2').returns([1,2,3,4,5,6]);
stub = proxyquire('./filelocation.js',{
'node-cache': stubCache
});
done();
});
it('should not throw error',(done)=>{
chai.expect(stub.testFunction()).not.to.throw;
});
})
I was Googling around, and there is some partial solution to use proxyquire to stub the value. but looks like it does stub but it's not where I wanted.
It stubs at NodeCache but cache
So I have questions:
Does anybody know how to stub cache.get() with mocha, chai or sinon? If so, please share how you do it ?
Is it possible to stub different returns by the argument of cache.get()?
Here is the unit test solution:
index.js:
const NodeCache = require("node-cache");
const cache = new NodeCache();
const testFunction = () => {
let myStringCache = cache.get("cacheName1");
let myArrayCache = cache.get("cacheName2");
console.log("myStringCache:", myStringCache);
console.log("myArrayCache:", myArrayCache);
return "return something";
};
module.exports = {
testFunction
};
index.spec.js:
const sinon = require("sinon");
const proxyquire = require("proxyquire");
const chai = require("chai");
describe("sample test with testFunction() ", () => {
let stubCache;
let stub;
let getCacheStub;
before(() => {
sandbox = sinon.createSandbox();
getCacheStub = sandbox.stub();
stubCache = sandbox.stub().callsFake(() => {
return {
get: getCacheStub
};
});
getCacheStub.withArgs("cacheName1").returns("sample string");
getCacheStub.withArgs("cacheName2").returns([1, 2, 3, 4, 5, 6]);
stub = proxyquire("./", {
"node-cache": stubCache
});
});
it("should not throw error", () => {
const logSpy = sinon.spy(console, "log");
chai.expect(stub.testFunction()).not.to.throw;
sinon.assert.calledWith(
logSpy.firstCall,
"myStringCache:",
"sample string"
);
sinon.assert.calledWith(logSpy.secondCall, "myArrayCache:", [
1,
2,
3,
4,
5,
6
]);
});
});
Unit test result with 100% coverage:
sample test with testFunction()
myStringCache: sample string
myArrayCache: [ 1, 2, 3, 4, 5, 6 ]
✓ should not throw error
1 passing (87ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.js | 100 | 100 | 100 | 100 | |
index.spec.js | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/58278211
I have two functions funcA and funcB
funcA is being an npm module, and funcB is custom function that calls funcA
funcB.js:
const a = require('a')
const funcB = ()=> a.funcA({arg})
I want to test that a.funcA has been called when invoking funcB
funcB.test.js:
describe("", () => {
it("should call a.funcA", () => {
sandbox.stub(a, "funcA");
funcB();
expect(a.funcA).to.have.been.called;
});
});
funcA:
function funcA() {
//....
return function c() {
//other logic here.
};
}
When i run test, i get this message:
I got a.funcA is not a spy or a call to a spy! error
How do i stub funcA? any ideas? ive tried mockquire but wouldnt work.
Here is the unit test solution:
funcB.js:
const a = require("./a");
const funcB = () => a.funcA({ arg: 123 });
exports.funcB = funcB;
a.js:
exports.funcA = function funcA(args) {
return function c() {};
};
funcB.test.js:
const { expect } = require("chai");
const sinon = require("sinon");
const a = require("./a");
const { funcB } = require("./funcB");
describe("57796168", () => {
let sandbox;
before(() => {
sandbox = sinon.createSandbox();
});
it("should call a.funcA", () => {
const funcAStub = sandbox.stub(a, "funcA");
funcB();
sinon.assert.calledWith(funcAStub, { arg: 123 });
expect(funcAStub.callCount).to.be.equal(1);
expect(funcAStub.calledWith({ arg: 123 })).to.be.true;
});
});
Unit test result with coverage report:
57796168
✓ should call a.funcA
1 passing (10ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 94.74 | 100 | 66.67 | 94.44 | |
a.js | 50 | 100 | 0 | 50 | 2 |
funcB.js | 100 | 100 | 100 | 100 | |
funcB.test.js | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/57796168
My unit test failing for following code.when I run test i see below result with unknown error.I am not getting how to test second parameter paylod in console.log method.
Test console log()
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 66.67 | 100 | 0 | 66.67 | |
logger.js | 66.67 | 100 | 0 | 66.67 | 6 |
-----------|----------|----------|----------|----------|-------------------|
npm ERR! Test failed. See above for more details.
//logger.js
'use strict';
const log = (message, payload) => {
console.log(message, JSON.stringify(payload, null, 2));
};
module.exports = { log };
// log.test.js
'use strict';
const chai = require('chai');
const sinon = require('sinon');
chai.use(require('sinon-chai'));
const { expect } = chai;
const log = require('../../src/logger');
describe('Test console log()', () => {
it('should log value in console', () => {
this.stub = sinon.stub(console, 'log');
log('test invoked', { option: 1 });
});
});
Looks like you just need to destructure your require for logger.js:
'use strict';
const sinon = require('sinon');
const { log } = require('../../src/logger'); // <= destructuring assignment
describe('Test console log()', () => {
it('should log value in console', () => {
const stub = sinon.stub(console, 'log');
log('test invoked', { option: 1 });
stub.restore();
sinon.assert.calledWith(stub, 'test invoked', JSON.stringify({ option: 1 }, null, 2)); // Success!
});
});
What would be the proper way to unit test this getall function using mocha/chai? I'm having a hard time understanding what to expect with Promise.all.
const Promise = require('bluebird');
const someApiService = require('./someapiservice');
const _ = require('underscore');
function getall(arr) {
let promises = _.map(arr, function(item) {
return someApiService(item.id);
});
return Promise.all(promises);
}
We should stub standalone function someApiService use link seams. This is the CommonJS version, so we will be using proxyquire to construct our seams. Additionally, I use sinon.js to create the stub for it.
E.g.
getall.js:
const Promise = require('bluebird');
const someApiService = require('./someapiservice');
const _ = require('underscore');
function getall(arr) {
let promises = _.map(arr, function (item) {
return someApiService(item.id);
});
return Promise.all(promises);
}
module.exports = getall;
someapiservice.js:
module.exports = function someApiService(id) {
return Promise.resolve('real data');
};
getall.test.js:
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const { expect } = require('chai');
describe('45337461', () => {
it('should pass', async () => {
const someapiserviceStub = sinon.stub().callsFake((id) => {
return Promise.resolve(`fake data with id: ${id}`);
});
const getall = proxyquire('./getall', {
'./someapiservice': someapiserviceStub,
});
const actual = await getall([{ id: 1 }, { id: 2 }, { id: 3 }]);
expect(actual).to.deep.equal(['fake data with id: 1', 'fake data with id: 2', 'fake data with id: 3']);
sinon.assert.calledThrice(someapiserviceStub);
});
});
unit test result:
45337461
✓ should pass (2745ms)
1 passing (3s)
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 88.89 | 100 | 66.67 | 88.89 |
getall.js | 100 | 100 | 100 | 100 |
someapiservice.js | 50 | 100 | 0 | 50 | 2
-------------------|---------|----------|---------|---------|-------------------