I'm using Jest with Typescript and I want to override the default mock implementation in some tests.
Suppose I have the following Foo class:
// foo.ts
export class Foo {
do(param?: string): string {
return param ?? 'default';
}
}
And its related tests:
// foo.spec.ts
import {Foo} from './foo';
import {mocked} from "ts-jest/utils";
jest.mock('./foo', () => ({
Foo: jest.fn(() => {
return {
do: jest.fn().mockReturnValue("bar"),
};
})
}));
describe('foo tests', function () {
// Test 1
it('test default mock', function () {
const foo = new Foo();
expect(foo.do()).toEqual('bar');
});
// Test 2
it('test override default mock - ok 1', function () {
const mockedFoo = mocked(Foo, true);
expect(mockedFoo).toBeTruthy();
mockedFoo.mockImplementationOnce(() => new class extends Foo {
do = jest.fn().mockImplementationOnce(() => "override ok");
});
const foo = new Foo();
expect(foo.do()).toEqual('override ok');
});
// Test 3
it('test override default mock - ok 2', function () {
const mockedFoo = mocked(Foo, true);
expect(mockedFoo).toBeTruthy();
mockedFoo.mockImplementationOnce(jest.fn<Foo, []>(
() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const self = this as Foo;
self.do = jest.fn().mockImplementationOnce(() => "override ok 2");
return self;
}
));
const foo = new Foo();
expect(foo.do()).toEqual('override ok 2');
});
// Test 4
it('test override default mock - not working', function () {
const mockedFoo = mocked(Foo, true);
expect(mockedFoo).toBeTruthy();
mockedFoo.prototype.do = jest.fn().mockImplementationOnce(() => "override not working");
const foo = new Foo();
expect(foo.do()).toEqual('bar');
});
});
As shown, the following tests work as expected:
- 'test default mock' (Test 1)
- 'test override default mock - ok 1' (Test 2)
- 'test override default mock - ok 2' (Test 3)
The test 'test override default mock - not working' (Test 4) doesn't work as expected (the default mock is not overridden).
Therefore, my questions are:
- why Test 4 does not override the default mock implementation?
- Is Test 2's implementation the recommended way of doing it (anonymous class) versus Test 3's approach (ignore typescript checks)?
- Is there a "better" way to override the default mock implementation?