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

Posted

技术标签:

【中文标题】使用动态导入时玩笑与自定义错误类型不匹配【英文标题】:jest not matching custom error type when using dynamic import 【发布时间】:2020-06-27 01:32:21 【问题描述】:

我定义了这个自定义错误(文件名:'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,以便我可以调用 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】:

我发现的解决方法是这样的:

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);
    );
);

【讨论】:

以上是关于使用动态导入时玩笑与自定义错误类型不匹配的主要内容,如果未能解决你的问题,请参考以下文章

opsworks rails.env 与自定义 json rails_env 不匹配

boost::asio::async_read_until 与自定义匹配条件运算符重载混淆

Qt 将信号与自定义插槽匹配

将 Shiro 的 PasswordMatcher 与自定义领域一起使用

Flutter ReorderableListView 与自定义对象

VSCode 无法识别开玩笑的自定义匹配器