Reputation: 377
I am trying to mock the function that returns another function. However, I am not sure how to get this done using jest. Thanks in advance.
Module needed to be mocked:
const initGreeter = () =>{
return {
sayHello: (name:string) =>{
console.log(`Hello: ${name}`)
}
}
}
export default initGreeter;
The module under test:
import initGreeter from './greeter';
export const greetSomeone = (name:string) =>{
const greeter = initGreeter();
greeter.sayHello(name)
}
Tests:
import initGreeter from '../../utils/greeter';
import { greetSomeone } from '../../utils/greeterConsumer';
describe('greeterConsumer', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('greeter consumer should call SayHello on greeter', () => {
//TODO:mock greeter here
greetSomeone('sam');
expect(greeter.sayHello.mock.call[0][0]).toBe('sam');
});
it('greeter consumer throws exception', () => {
//TODO:mock greeter here so it throws exception
expect(greetSomeone('sam')).toThrow(Error);
});
});
Please note code in Update 1 and 2 are a continuation of the code in the solution from @slideshowp2.
Update 2: Looks like if the change the code below
jest.mock('./greeter', () => {
return jest.fn(() => mGreeter);
});
to
jest.mock('../../utils/greeter.ts', () => ({
__esModule: true,
default: jest.fn(() => mGreeter)
}));
it works.
There are other ways to make the code from @slideshowp2 to work as is, for example setting "esModuleInterop": true in tsconfig. However, I don't fully understand why it works for either case. I may check in the future and update here.
Update 1: after implementing the solution from @slideshowp2
I am getting the error below in my test
FAIL src/tests/utils/greeterConsumer.test.ts ● greeterConsumer › greeter consumer should call SayHello on greeter
TypeError: greeter_1.default is not a function
2 |
3 | export const greetSomeone = (name:string) =>{
> 4 | const greeter = initGreeter();
| ^
5 | greeter.sayHello(name)
6 | }
at Object.<anonymous>.exports.greetSomeone (src/utils/greeterConsumer.ts:4:21)
at Object.<anonymous> (src/__tests__/utils/greeterConsumer.test.ts:18:5)
Upvotes: 2
Views: 9749
Reputation: 9623
I use below to mock logger , which return logger instance with logging methods
jest.mock('logging', () => ({
getLogger: jest.fn().mockReturnValue({
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
})
}
));
Upvotes: 0
Reputation: 102237
You can use jest.mock(moduleName, factory, options) to mock ../../utils/greeter
module manually.
E.g.
greeter.ts
:
const initGreeter = () => {
return {
sayHello: (name: string) => {
console.log(`Hello: ${name}`);
},
};
};
export default initGreeter;
greeterConsumer.ts
:
import initGreeter from './greeter';
export const greetSomeone = (name: string) => {
const greeter = initGreeter();
greeter.sayHello(name);
};
greeterConsumer.test.ts
:
import initGreeter from './greeter';
import { greetSomeone } from './greeterConsumer';
const mGreeter = {
sayHello: jest.fn(),
};
jest.mock('./greeter', () => {
return jest.fn(() => mGreeter);
});
describe('greeterConsumer', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('greeter consumer should call SayHello on greeter', () => {
greetSomeone('sam');
expect(initGreeter).toBeCalledTimes(1);
expect(mGreeter.sayHello).toBeCalledWith('sam');
});
it('greeter consumer throws exception', () => {
mGreeter.sayHello.mockImplementationOnce(() => {
throw new Error('oops');
});
expect(() => greetSomeone('sam')).toThrowError('oops');
expect(initGreeter).toBeCalledTimes(1);
expect(mGreeter.sayHello).toBeCalledWith('sam');
});
});
unit test result:
PASS examples/65281989/greeterConsumer.test.ts
greeterConsumer
✓ greeter consumer should call SayHello on greeter (3 ms)
✓ greeter consumer throws exception (10 ms)
--------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
greeterConsumer.ts | 100 | 100 | 100 | 100 |
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.473 s
source code: https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/65281989
Upvotes: 4