开玩笑使用动态导入时不匹配自定义错误类型

时间:2020-03-15 20:42:39

标签: typescript jestjs

我定义了此自定义错误(文件名:'errors.ts'):

export class CustomError extends Error {
    constructor(message?: string) {
        super(message);
        Object.setPrototypeOf(this, Error.prototype);
        this.name = this.constructor.name;
    }
}

我有这个模块使用该错误(文件名:'main.ts'):

import { CustomError } from './errors';

let called = false;
export default {
    throwAfterFirst: (): void => {
        if (called) throw new CustomError();
        called = true;
    },
};

我想通过动态导入来开玩笑地检查,因此我可以调用jest.restModule()来重置called变量。这是测试文件:

import { CustomError } from './errors';

let main: typeof import('./main').default;
const load = async (): Promise<Main> => {
    jest.resetModules();
    main = (await import('./main')).default;
};

describe('Main', () => {
    beforeEach(async () => {
        await load();
    });

    it('should throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(CustomError);
    });

    it('should still throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(CustomError);
    });
});

现在这工作了一半,因为确实在每次测试之前都会重置模块,但是问题是toThrowError不能正确匹配,第二行的两个测试都出现以下错误:

expect(received).toThrowError(expected)

Expected constructor: CustomError
Received constructor: CustomError
.
.
.

这个奇怪的错误不会因常规错误而发生(例如,将CustomError替换为TypeError)。
另外,CustomError可以成功匹配而无需动态导入。 例如,以下测试可以正常工作:

import { CustomError } from './errors';
import main from './main';

describe('Main', () => {
    it('should throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(CustomError);
    });
});

由于我使用的是动态导入CustomError,因此无法正确识别(也许不是同一原型?)。我在这里缺少什么,如何修复测试?
(我仍然想检查特定的错误,不使用与任何错误匹配的toThrow。顺便说一句,toThrow适用于这种情况)。

1 个答案:

答案 0 :(得分:0)

我发现的解决方法是:

let main: typeof import('./main').default;
let Errors: typeof import('./errors');
const load = async (): Promise<void> => {
    jest.resetModules();
    main = (await import('./main')).default;
    Errors = await import('./errors');
};

describe('Main', () => {
    beforeEach(async () => {
        await load();
    });

    it('should throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(Errors.CustomError);
    });

    it('should still throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(Errors.CustomError);
    });
});