I'm struggling to figure out how to do this.
example.js
import Logger from "logging-library";
export default function example() {
Logger.error(new Error("Example Error")):
}
example.test.js
test("will log an error", () => {
expect(Logger.error).toHaveBeenCalledWith(new Error("Example Error");
});
The examples I've found might cover mocking an entire library, but don't seem to cover mocking and also asserting how it was called.
unit test solution:
example.js:
import Logger from 'logging-library';
export default function example() {
Logger.error(new Error('Example Error'));
}
example.test.js:
import Logger from 'logging-library';
import example from './example';
jest.mock(
'logging-library',
() => {
return { error: jest.fn() };
},
{ virtual: true },
);
describe('64858662', () => {
afterAll(() => {
jest.resetAllMocks();
});
test('will log an error', () => {
example();
expect(Logger.error).toHaveBeenCalledWith(new Error('Example Error'));
});
});
unit test result:
PASS src/stackoverflow/64858662/example.test.js
64858662
✓ will log an error (5ms)
------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
example.js | 100 | 100 | 100 | 100 | |
------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.373s, estimated 12s
Related
I have a code like this
import fun from '../../../example';
export async function init (props:any){
if (fun()){
doSomething();
}
}
I'm creating unit tests for this code above, but I actually want to mock the implementation of fun in the file only as I can't alter fun in its original file
You can use jest.mock(moduleName, factory, options) to mock ../../../example module.
E.g.
index.ts:
import fun from './example';
export async function init(props: any) {
if (fun()) {
console.log('doSomething');
}
}
example.ts:
export default function fun() {
console.log('real implementation');
return false;
}
index.test.ts:
import { init } from './';
import fun from './example';
import { mocked } from 'ts-jest/utils';
jest.mock('./example', () => jest.fn());
describe('63166775', () => {
it('should pass', async () => {
expect(jest.isMockFunction(fun)).toBeTruthy();
const logSpy = jest.spyOn(console, 'log');
mocked(fun).mockReturnValueOnce(true);
await init({});
expect(logSpy).toBeCalledWith('doSomething');
expect(fun).toBeCalledTimes(1);
logSpy.mockRestore();
});
});
unit test result:
PASS stackoverflow/63166775/index.test.ts (13.298s)
63166775
✓ should pass (33ms)
console.log
doSomething
at CustomConsole.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
index.ts | 100 | 50 | 100 | 100 | 4
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 15.261s
I want to mock the resolve method that is part of the "path" module.
I am using it in a method and i want to mock the response of path.resolve(filepath) so i can write some unitTests based on that.
You can jest.spyOn(object, methodName) to mock path.resolve method.
E.g.
main.ts:
import path from 'path';
export function main(filepath) {
return path.resolve(filepath);
}
main.test.ts:
import { main } from './main';
import path from 'path';
describe('61419093', () => {
it('should pass', () => {
const resolveSpy = jest.spyOn(path, 'resolve').mockReturnValueOnce('/fakepath');
const actual = main('/root/avatar.jpg');
expect(actual).toBe('/fakepath');
expect(resolveSpy).toBeCalledWith('/root/avatar.jpg');
resolveSpy.mockRestore();
});
});
unit test results with 100% coverage:
PASS stackoverflow/61419093/main.test.ts (12.631s)
61419093
✓ should pass (4ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
main.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 14.426s
I have a function, lets call it generateName, which as you’ve guessed it, generates a name. The problem is that a new name is generated each time time a test is ran.
In one of my tests, I assert that a function is called with an object containing this name. However, the name keeps on changing. I could just check that the object has property name, but I don’t really want to do that.
My idea is that I can mock the return value of the generateName function and do something like this
Import { generateName } from ‘libs/generateName’
jest.fn(generateName).mockResolvedValue ( ‘hello’ )
expect ( spy ).toHaveBeenCalledWith (
expect.objectContaining ( {
name: 'houses',
} )
)
You can use jest.mock(moduleName, factory, options) to mock libs/generateName module.
E.g.
generateName.ts:
export async function generateName() {
const name = Math.random() + '';
return name;
}
main.ts:
import { generateName } from './generateName';
export function main() {
return generateName();
}
main.test.ts:
import { main } from './main';
import { generateName } from './generateName';
jest.mock('./generateName', () => {
return {
generateName: jest.fn(),
};
});
describe('61350152', () => {
it('should pass', async () => {
(generateName as jest.MockedFunction<typeof generateName>).mockResolvedValueOnce('hello');
const actual = await main();
expect(actual).toBe('hello');
});
});
unit test results with coverage report:
PASS stackoverflow/61350152/main.test.ts (28.524s)
61350152
✓ should pass (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
main.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 31.98s
This is an example of my class:
class MyClass {
constructor() {
this.myLib = new MyLib()
}
myMainMethod = param => {
this.myLib.firstMethod(arg => {
arg.secondMethod(param)
})
}
}
Using Jest, how can I assert that "secondMethod" will be called with I call "myMainMethod".
MyLib is a third-party library.
Here is the unit test solution:
index.ts:
import { MyLib } from './MyLib';
export class MyClass {
myLib;
constructor() {
this.myLib = new MyLib();
}
myMainMethod = (param) => {
this.myLib.firstMethod((arg) => {
this.myLib.secondMethod(arg);
});
};
}
index.test.ts:
import { MyClass } from './';
import { MyLib } from './MyLib';
describe('60840838', () => {
it('should pass', () => {
const firstMethodSpy = jest.spyOn(MyLib.prototype, 'firstMethod').mockImplementationOnce((callback) => {
callback('arg');
});
const secondMethodSpy = jest.spyOn(MyLib.prototype, 'secondMethod').mockReturnValueOnce('fake');
const instance = new MyClass();
instance.myMainMethod('param');
expect(firstMethodSpy).toBeCalledWith(expect.any(Function));
expect(secondMethodSpy).toBeCalledWith('arg');
});
});
unit test results with coverage report:
PASS stackoverflow/60840838/index.test.ts
60840838
✓ should pass (4ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 87.5 | 100 | 71.43 | 85.71 |
MyLib.ts | 71.43 | 100 | 33.33 | 66.67 | 3,6
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.54s, estimated 8s
I am unable to mock 3rd party function call in typescript.
The third party library is moment-timezone and I want to mock the code to get browser timezone to write jest test.
Below is the code I need to mock and return string as 'Australia/Sydney'
moment.tz.guess()
I am trying to use jest.mock() as :-
jest.mock('moment-timezone', () => () => ({ guess: () => 'Australia/Sydney' }));
Here is the solution:
index.ts:
import moment from 'moment-timezone';
export function main() {
return moment.tz.guess();
}
index.spec.ts:
import { main } from './';
import moment from 'moment-timezone';
jest.mock('moment-timezone', () => {
const mTz = {
guess: jest.fn()
};
return {
tz: mTz
};
});
describe('main', () => {
test('should mock guess method', () => {
(moment.tz.guess as jest.MockedFunction<typeof moment.tz.guess>).mockReturnValueOnce('Australia/Sydney');
const actualValue = main();
expect(jest.isMockFunction(moment.tz.guess)).toBeTruthy();
expect(actualValue).toBe('Australia/Sydney');
expect(moment.tz.guess).toBeCalled();
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/58548563/index.spec.ts
main
✓ should mock guess method (6ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.828s, estimated 19s