I have the following typescript class which I want to test in Jest.
//MyClass.ts
import { foo } from './somewhere/FooFactory';
export class MyClass {
private _state : number;
constructor( arg : string ) {
this._state = foo( arg );
}
public getState() : string {
return this._state;
}
}
This is my test:
//MyClass.spec.ts
import { MyClass } from './MyClass';
describe( 'test MyClass', () => {
test( 'construct' => {
const c = new MyClass( 'test' );
expect( c ).toBeDefined();
expect( c.getState() ).toEqual( 'TEST' );
} );
} );
How do I mock the foo function used inside MyClass so that this test passes?
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
Let's refactor the test to use this approach: test("Should render character name", async () => { const mock = jest. spyOn(data, "getCharacter"). mockResolvedValue("Bob"); render(<Hello id={1} />); expect(await screen.
fn method allows us to create a new mock function directly. If you are mocking an object method, you can use jest. spyOn . And if you want to mock a whole module, you can use jest.
In Jest, Node. js modules are automatically mocked in your tests when you place the mock files in a __mocks__ folder that's next to the node_modules folder. For example, if you a file called __mock__/fs. js , then every time the fs module is called in your test, Jest will automatically use the mocks.
There are a few different ways to approach it.
You can mock only foo
using jest.spyOn
and something like mockImplementation
:
import { MyClass } from './MyClass';
import * as FooFactory from './somewhere/FooFactory';
describe('test MyClass', () => {
test('construct', () => {
const mock = jest.spyOn(FooFactory, 'foo'); // spy on foo
mock.mockImplementation((arg: string) => 'TEST'); // replace implementation
const c = new MyClass('test');
expect(c).toBeDefined();
expect(c.getState()).toEqual('TEST'); // SUCCESS
mock.mockRestore(); // restore original implementation
});
});
Similarly, you can auto-mock FooFactory
with jest.mock
, then provide an implementation for foo
:
import { MyClass } from './MyClass';
import * as FooFactory from './somewhere/FooFactory';
jest.mock('./somewhere/FooFactory'); // auto-mock FooFactory
describe('test MyClass', () => {
test('construct', () => {
const mockFooFactory = FooFactory as jest.Mocked<typeof FooFactory>; // get correct type for mocked FooFactory
mockFooFactory.foo.mockImplementation(() => 'TEST'); // provide implementation for foo
const c = new MyClass('test');
expect(c).toBeDefined();
expect(c.getState()).toEqual('TEST'); // SUCCESS
});
});
You can also mock FooFactory
using a module factory passed to jest.mock
:
import { MyClass } from './MyClass';
jest.mock('./somewhere/FooFactory', () => ({
foo: () => 'TEST'
}));
describe('test MyClass', () => {
test('construct', () => {
const c = new MyClass('test');
expect(c).toBeDefined();
expect(c.getState()).toEqual('TEST'); // SUCCESS
});
});
And finally, if you plan to use the same mock across multiple test files you can mock the user module by creating a mock at ./somewhere/__mocks__/FooFactory.ts
:
export function foo(arg: string) {
return 'TEST';
}
...then call jest.mock('./somewhere/FooFactory');
to use the mock in the test:
import { MyClass } from './MyClass';
jest.mock('./somewhere/FooFactory'); // use the mock
describe('test MyClass', () => {
test('construct', () => {
const c = new MyClass('test');
expect(c).toBeDefined();
expect(c.getState()).toEqual('TEST'); // SUCCESS
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With