using sinon to mock a line in a function - javascript

I have a function as follows
import config from "../config";
export const encrypt = (recordJSONy, logger) => {
const key = config.encryption.key
if(!key || key == ""){
throw encryptionError.ENCYPTION_KEY_MISSING
}
try{
const decryptedDataStr = TisEncryption.Cipher.encrypt(recordJSON);
return decryptedDataStr;
} catch(e){
console.log(e)
throw encryptionError.ENCRYPTION_FAILED
}
}
I need to write a test for it
describe("help function test", () => {
it("test", () => {
console.log(helperFunctions.encrypt("xxx", loggingService))
});
});
However the above is always returning error because config.encryption.key returns undefined.
I am trying to find a way to kind of mock config.encryption.key to return "xxxxxxx" instead of undefined. The more I look at sinon the more I get confused. Can anyone shed light on how to do so?

Related

How to mock child function with Jest

I have a sendMail.js class content as below
export default function registerEmailHandlers() {
const sendMailAsync = async (emailAddress) => {
return await sendMail();
}
return {
sendMailAsync
}
}
How can I write Jest mock for this type of code?
I want mock sendMailAsync always return 'some test'.
I tried to research but nothing same that what I want.
Could you do something like
const mockSendMailAsync = jest.fn());
jest.mock('./path/to/file/sendMail', () => (
sendMailAsync = mockSendMailAsync
)
Then you could assert that mockSendMailAsync has been called

Jest mocks - how to restore original function between tests

I have my function:
report.js:
const ctrl = {};
const _ = require('lodash');
const boom = require("boom");
const slackNotifications = require('./../../slack/controllers/notifications');
const reportModel = require("./../models/report");
import validationSchema from "./../_validation/report";
ctrl.addReport = async (req, res) => {
const { body } = req;
try {
const validatedData = await validationSchema.validate(body);
const report = await reportModel(req.dbConnection).addReport(validatedData);
if (report.reported) {
await slackNotifications.notify('Notify me!');
res.status(200).send({ reported: true });
} else {
throw boom.serverUnavailable("Can't offer report");
}
} catch (err) {
throw boom.badRequest(err);
}
};
module.exports = ctrl;
The validation schema is schema created by using yup.js.
Here are the tests
The problem is throw Error when validation failed test. I've got
TypeError: Cannot read property 'output' of undefined
from 109 line
const { output, output: { payload } } = err;.
But my expected value is error threw by validationSchema.validate and caught in 23rd line of my function.
When I run only this test everything is ok. I've got the correct error with status code and message.
How can I restore the original function validationSchema.validate from this test (84th line)?
I've tried to restore by:
jest.mock('./../_validation/report', () => ({
// validate: jest.fn().mockReset(),
validate: jest.fn().mockClear(),
}));
But I'm not sure that is the correct way.
You can use requireActual in your test to execute the original behaviour for just one test.
This way :
jest.mock('./../_validation/report', () => ({
validate: jest.requireActual('./../_validation/report').validate,
}));
This way, the real validate will be called
Of course, at the next test (or in a beforeEach), you can re-mock your function.

Jest mocking a module

I'm trying to mock a module import using Jest and I'm struggling for some reason. I've got the following code:
src/elastic.js
const getRolesFunc = elasticClient => async username => {
// Do some stuff
}
module.exports = { getRolesFunc };
src/handlerFactory.js
const { getRolesFunc } = require("../src/elastic");
const handlerFactory = elasticClient =>
async (event) => {
const getRolesAsync = getRolesFunc(elasticClient);
const roles = await getRolesAsync();
}
}
My test file currently looks like:
tests/handlerFactory.unit.test.js
const { handlerFactory } = require("../src/handlerFactory");
const { getRolesFunc } = require("../src/elastic");
jest.mock("../src/elastic", () => ({
getRolesFunc: jest.fn(),
}));
describe("handlerFactory", () => {
it("handler returns correct response", async () => {
getRolesFunc.mockImplementation(() => "foo");
// Call the handler to get our actual result
const handlerAsync = handlerFactory({});
const result = await handlerAsync(event);
});
});
At the moment however I'm getting an error in my test:
TypeError: getRolesFunc.mockImplementation is not a function
I've tried a few things none of which worked, this feels like the closest but I can't work out why the jest.mock isn't working correctly. I've looked at a few examples and still can't work out why this I can't get mocking working. Can anyone help point out what I've done wrong?
As you have module.exports = { getRolesFunc }; you need to below change in your code:
const { handlerFactory } = require("../src/handlerFactory");
const elasticObj = require("../src/elastic");
jest.mock("..src/elastic");
// in your example, now put below code:
elasticObj.getRolesFunc.mockImplementation(() => "foo");

Node.js unittest Stubbing Own function

Apologies if this was asked before. Here is the module that I'd like to unittest inside file getStuff.js. I'm having difficulty stubbing theresolveThing module used here.
getStuff.js
const resolveThing = require('./resolveThing.js');
module.exports = async function getStuff(target, stuff) {
const { element, test, other } = resolveThing(target);
try {
return element;
} catch (error) {
throw new Error('Did not work.');
}
};
And here is my attempt at the unittest with stubbing using sinon. However when I try to run this it errors out with TypeError: Cannot stub non-existent own property resolveType. Anyone know how I can get this test to work?
const getStuff = require('../com/getStuff');
const resolveThing = require('../com/resolveThing');
const mochaccino = require('mochaccino');
const { expect } = mochaccino;
const sinon = require('sinon');
describe('com.resolveThing', function() {
beforeEach(function () {
sinon.stub(resolveThing, 'resolveThing').returns({element:'a',test:'b',other:'c'});
});
afterEach(function () {
resolveThing.restore();
});
it('Standard message', function() {
const answer = getAttribute('a','b');
expect(answer).toEqual('a');
});
});
sinon.stub(resolveThing, 'resolveThing').returns({element:'a',test:'b',other:'c'});
resolveThing must be an object and 'resolveThing' must be a function in the object, an exception is thrown if the property is not already a function.
I think this is what's hapning in your case.

sinon stub not replacing function

I'm trying to use sinon stub to replace a function that might take along time. But when I run the tests, the test code doesn't seem to be using the sinon stubs.
Here is the code I'm trying to test.
function takeTooLong() {
return returnSomething();
}
function returnSomething() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('ok')
}, 1500)
})
}
module.exports = {
takeTooLong,
returnSomething
}
and this is the test code.
const chai = require('chai')
chai.use(require('chai-string'))
chai.use(require('chai-as-promised'))
const expect = chai.expect
chai.should()
const db = require('./database')
const sinon = require('sinon')
require('sinon-as-promised')
describe('Mock the DB connection', function () {
it('should use stubs for db connection for takeTooLong', function (done) {
const stubbed = sinon.stub(db, 'returnSomething').returns(new Promise((res) => res('kk')));
const result = db.takeTooLong()
result.then((res) => {
expect(res).to.equal('kk')
sinon.assert.calledOnce(stubbed);
stubbed.restore()
done()
}).catch((err) => done(err))
})
I get an assertion error
AssertionError: expected 'ok' to equal 'kk'
+ expected - actual
-ok
+kk
What am I doing wrong? Why isn't the stub being used ? The test framework in Mocha.
Sinon stubs the property of the object, not the function itself.
In your case you are exporting that function within an object.
module.exports = {
takeTooLong,
returnSomething
}
So in order to properly call the function from the object, you need to replace your function call with the reference to the export object like :
function takeTooLong() {
return module.exports.returnSomething();
}
Of course based on your code, you can always refactor it :
var exports = module.exports = {
takeTooLong: function() { return exports.returnSomething() }
returnSomething: function() { /* .. */ }
}
You might want to have a look at Proxyquire to stub/spy directly exported functions.
https://www.npmjs.com/package/proxyquire/

Categories