Jest: testing inner function is called - jestjs

Given the below, how do I make sure that the inner foo function is called with the correct message when the bar function is executed? Thanks.
const foo = (message) => console.log(message);
const bar = () => foo('this is a message');
test('test that the foo function is called with the correct message when the bar' +
' function is executed', () => {
bar();
expect(foo).toHaveBeenCalledWith('this is a message');
});

You need to mock foo function like this:
let foo = message => console.log(message)
const bar = () => foo('this is a message')
test('test that the foo function is called with the correct message when the bar function is executed', () => {
foo = jest.fn()
bar()
expect(foo).toHaveBeenCalledWith('this is a message')
})

Related

How can I count calls to a looped Promise function with Jest

I have a function:
myFunc = async () => {
for (let item of items) {
await doSomething(items);
}
}
I use for of loop because it respects await.
My test:
it('should call doSomething twice', () => {
const doSomething = jest.fn();
const items = [{a: 'a'}, {b: 'b'}];
myFunc(items);
expect(doSomething).toBeCalledTimes(2);
})
It fails because doSomething is only called once.
You will need to wait for all the iterations to be completed.
Try something like this:
it('should call doSomething twice', async () => {
const doSomething = jest.fn();
const items = [{a: 'a'}, {b: 'b'}];
// Waiting
await myFunc(items);
expect(doSomething).toBeCalledTimes(2);
})

Mocha: Can't stub function in file that was already required in another test file

I'm using Mocha to run a test suite on fileToTest.js with requires greeting.js
// --fileToTest.js--
const { greeting } = require('./greeting');
module.exports = () => greeting();
// --greeting.js--
module.exports.greeting = () => 'hi!';
By itself, this test file successfully stubs greeting.
// --test2.js--
let parent;
const sinon = require('sinon');
const chai = require('chai');
const greeting = require('../../greeting.js');
const { expect } = chai;
describe('stubbed /hi', () => {
before(async () => {
sinon.stub(greeting, 'greeting').callsFake((req, res, next) => 'bye!');
parent = require('../../parent.js');
});
after(async () => {
greeting.greeting.restore();
});
it('should say bye', async function () {
expect(parent()).to.be.equal('bye!');
});
});
However if I run a test suite and have another test file that requires fileToTest.js, like test1.js below, the first test above (test2.js) won't stub greeting.
// --test1.js--
const chai = require('chai');
const fileToTest = require('../../fileToTest.js');
const { expect } = chai;
describe('not stubbed /hi', () => {
it('should say hi', () => {
expect(fileToTest()).to.be.equal('hi!');
});
});
It seems once test1.js requires fileToTest, mocha doesn't reload the fileToTest on the test2.js's require. So fileToTest is stuck with the old greeting function.
Whats the proper way to stub a function in this situation?
Repo
This answer worked. I had to delete the cache.
before(async () => {
delete require.cache[require.resolve('../../fileToTest.js')]; // <------
sinon.stub(greeting, 'greeting').callsFake((req, res, next) => 'bye!');
fileToTest = require('../../fileToTest.js');
});

Jest mock nested function by using spyOn, but still call the actual function

getInfo calls getColor in the same file. My intention is to mock getColor function, I import the func.js as a module and spyOn getColor. The mocked getColor is supposed to return "Red", but it still calls the actual function and returns "Black".
Function File
// func.js
function getColor() {
return "black"
}
function getInfo(){
const color = getColor()
const size = "L"
return `${color}-${size}`
}
module.exports = { getColor, getInfo }
Test File
// func.test.js
const func = require("./func")
describe("Coverage Change Test", () => {
beforeAll(() => {
const colorMock = jest.spyOn(func, "getColor"); // spy on otherFn
colorMock.mockImplementation(() => "Red");
});
afterAll(() => {
colorMock.resetAllMocks();
})
test("return Large Red", async () => {
const res = func.getInfo();
expect(res).toEqual("Red-L");
});
});
I also tried requireActual, but it also calls the actual one.
const { getInfo, getColor } = require('./func');
jest.mock('./func', () => ({
...jest.requireActual('./func.'),
getColor: jest.fn().mockImplementation(() => 'Red'),
}))
describe('test', () => {
test('returns red', () => {
const res = getInfo()
expect(res).toEqual("Red-L")
})
})
How can I properly mock up a nested function in Jest? Thanks in advance.
You're spying on func.getColor and mocking its implementation but getInfo is calling the locally scoped getColor function. You have to change the way getColor is being called to be able to mock it.
exports.getColor = function() {
return 'black'
}
exports.getInfo = function() {
const color = exports.getColor()
const size = 'L'
return `${color}-${size}`
}
Use rewire module to rewrite your exported properties.
Your test file will look like this:
const rewire = require('rewire')
describe('test', () => {
let func;
let getColorSpy;
beforeEach(() => {
getColorSpy = jest.fn()
func = rewire(__dirname + '/func.js') // import
func.__set__('getColor', getColorSpy) // rewrite content of getColor
})
test('should return Red-L when getColor returns Red', () => {
getColorSpy.mockReturnValue('Red')
const res = func.getInfo()
expect(res).toEqual("Red-L")
})
})
Try to avoid write code like your module.

Testing a function which returns an object that returns a function which return a boolean

I have a situation where I want to test a function that has been called in an if statement. I don't know how to test this function which actually returns a boolean.
Code
function test(){
if(await SOP3loginConfig(props: object).isSOP3()){
//calls if statements
} else {
//calls else statements
}
}
In the above snippet, I am trying to test that function, I am able to do that, but can go through the if() branch.
I am using jest and react-testing-library.
I don't have access to the body of the functions within the if statements.
Tried this
it('Should call the SOP3 functions', () => {
props.user = {};
let SOP3loginConfig = (props: any) => {
console.log(' ========================= I A M A TEST');
return {
isSOP3: () => {
console.log(' ================ iSOP3 called');
return true;
},
};
};
functions.start(props);
expect(SOP3loginConfig(props).isSOP3()).toHaveBeenCalled();
expect(props.history.push).not.toHaveBeenCalled();
});
But got this error !
expect(received).toHaveBeenCalled()
Matcher error: received value must be a mock or spy function
Received has type: boolean
Received has value: true
229 | };
230 | functions.start(props);
> 231 | expect(SOP3loginConfig(props).isSOP3()).toHaveBeenCalled();
| ^
232 | expect(props.history.push).not.toHaveBeenCalled();
233 | });
234 |
Try using jest.fn
it('Should call the SOP3 functions', () => {
props.user = {};
const isSOP3Mock = jest.fn(() => {
console.log(' ================ iSOP3 called');
return true;
})
let SOP3loginConfig = (props: any) => {
console.log(' ========================= I A M A TEST');
return {
isSOP3: isSOP3Mock,
};
};
functions.start(props);
expect(isSOP3Mock).toHaveBeenCalled();
expect(props.history.push).not.toHaveBeenCalled();
});
assuming the functions.start(props) will call your test function.

Understand the utility of mocks with Jest

I can't understand at all the utility of mockings. See, I have the next module:
function Code() {
this.generate = () => {
const result = 'code124';
return result;
};
}
module.exports = Code;
Now, I want to test it with jest:
const Code = require('../lib/code');
jest.mock('../lib/code', () => {
return jest.fn().mockImplementation(() => {
return {
generate: () => [1, 2, 3]
};
});
});
describe('Code', () => {
test('returns the code "code123"', () => {
const code = new Code();
expect(code.generate()).toBe('code123');
});
});
So... This test will be fine but... My code ain't so... what's the point about mocking if I can set a correct result even though my code is wrong?
You're NOT supposed to mock the unit you're testing. You're supposed to mock it's dependencies.
for example:
whenever you have a dependency in the implementation:
const dependency = require('dependency');
function Code() {
this.generate = () => {
const result = 'code' + dependency.getNumber();
return result;
};
}
module.exports = Code;
you'll be able to modify it's results to be able to test all scenarios without using the actual implementation of your dependency:
const dependency = require('dependency');
const Code = require('../lib/code');
jest.mock('dependency');
describe('Code', () => {
describe('when dependency returns 123', () => {
beforeAll(() => {
dependency.getNumber.mockReturnValue('123');
});
it('should generate code123', () => {
const code = new Code();
expect(code.generate()).toEqual('code123');
});
});
describe('when dependency returns 124', () => {
beforeAll(() => {
dependency.getNumber.mockReturnValue('124');
});
it('should generate code123', () => {
const code = new Code();
expect(code.generate()).toEqual('code124');
});
});
});

Resources