【问题标题】:How to let TypeScript know about custom Jest matchers?如何让 TypeScript 知道自定义 Jest 匹配器?
【发布时间】:2020-04-17 02:10:38
【问题描述】:

我有一个使用 jest 的 react/typescript 项目,其中我有一个自定义匹配器,例如:

export const MyCustomMatchers = {
    toBeTheSameAsRemote: function(_util: any, _customEqualityTesters: any) {
        return {
            compare: function(actual: Brand, expected: RemoteBrand) {
                const pass: boolean = attributesMatch(actual, expected);
                const message: string = pass
                    ? 'Local matches Remote'
                    : 'Local does not match Remote';

                return { pass, message: () => message };
            }
        };
    }
};

我在测试中通过在 describe 函数中引用它:

beforeEach(() => {
  jasmine.addMatchers(MyCustomMatchers);
});

并在it 函数中像这样使用:

expect(localValue).toBeTheSameAsRemote(remoteValue);

测试运行正常,但 typescript 编译器无法识别匹配器,这是有道理的,因为我没有在类型系统的任何地方定义它

Property 'toBeTheSameAsRemote' does not exist on type 'JestMatchersShape<Matchers<void, MyType[]>, Matchers<Promise<void>, MyType[]>>'.ts(2339)

到目前为止,我发现与扩展 jasmine 和/或 jest 的命名空间有关,例如

declare namespace jasmine {
    interface Matchers {
        toBeTheSameAsRemote(remote: any): any;
    }
}

这对我没有用。

你有什么想法吗?

【问题讨论】:

    标签: typescript types jestjs ts-jest jasmine-matchers


    【解决方案1】:

    试试这个:

    以下文件声明了实际的 实现 expect.extend 以及 TypeScript 声明。

    custom-matcher.ts:

    declare global {
      namespace jest {
        interface Matchers<R> {
            toBeTheSameAsRemote: (expected: string) => CustomMatcherResult;
        }
      }
    }
    
    expect.extend({
        /**
         * Notice that this implementation has 2 arguments, but the implementation inside the Matchers only has 1
         */
        toBeTheSameAsRemote(
        received: string,
        expected: string
      ) {
        return {
          pass: false,
          message: "A GraphQl error was expected"
        };
      }
    });
    
    // I am exporting nothing just so we can import this file
    export default undefined;
    
    

    现在,在您的测试文件中,导入上述模块。

    actual-test.ts:

    // importing the custom matcher file is important
    import "../../testing/custom-matchers/custom-matcher";
    
    describe("something", () => {
       it("should work", () => {
           expect(localValue).toBeTheSameAsRemote(remoteValue);
       });
    });
    

    注意事项:

    • expect.extend 将从导入中自动调用。无需对每个测试文件都调用expect.extend。
    • declare global 是必需的,因为 jest 没有显式导入(它是全局导入)。
    • toBeTheSameAsRemote 函数的签名在 expect.extend 内部和 TypeScript 上不同。

    【讨论】:

    • 在 Typescript v4 中 @typescript-eslint/no-namespace 失败并显示 ES2015 module syntax is preferred over custom TypeScript modules and namespaces。有没有比简单地禁用此规则更好的方法?或者只要jest 是全局的,就必须禁用?
    • ESLint:ES2015 模块语法优于自定义 TypeScript 模块和命名空间。(@typescript-eslint/no-namespace)
    猜你喜欢
    • 2020-05-30
    • 2017-10-02
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 2020-09-10
    • 2017-08-14
    • 2023-01-12
    相关资源
    最近更新 更多