首页 > 解决方案 > Jest 和 Typescript:覆盖默认模拟实现的推荐方法

问题描述

我将 Jest 与 Typescript 一起使用,并且我想在某些测试中覆盖默认的模拟实现。

假设我有以下 Foo 类:

// foo.ts
export class Foo {
    do(param?: string): string {
        return param ?? 'default';
    }
}

及其相关测试:

// 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');
    });
});

如图所示,以下测试按预期工作:

测试“测试覆盖默认模拟 - 不工作”(测试 4)没有按预期工作(默认模拟未被覆盖)。

因此,我的问题是:

  1. 为什么 Test 4 不覆盖默认的模拟实现?
  2. 测试 2 的实现是推荐的方法(匿名类)与测试 3 的方法(忽略打字稿检查)吗?
  3. 有没有“更好”的方法来覆盖默认的模拟实现?

标签: typescriptjestjs

解决方案


推荐阅读