如何让 Jest 自定义匹配器在打字稿中工作?

Posted

技术标签:

【中文标题】如何让 Jest 自定义匹配器在打字稿中工作?【英文标题】:How to get a Jest custom matcher working in typescript? 【发布时间】:2020-05-30 07:38:31 【问题描述】:

我经常进行单元测试,我需要比较两个矩对象。我要我们 moment 的内置函数 moment.isSame(moment) 来比较它们。但是,这意味着我的断言将如下所示:

expect(moment1.isSame(moment2)).toBeTrue();

我不太喜欢这样,尤其是因为失败消息的信息量较少。因此,我想编写一个自定义的笑话匹配器“toBeSameMoment”。以下代码似乎至少可以编译:

import moment from "moment";

declare global 
  namespace jest 
    interface MomentMatchers extends Matchers<moment.Moment> 
      toBeSameMoment: (expected: moment.Moment) => CustomMatcherResult;
    
  


expect.extend(
  toBeSameMoment(received: moment.Moment, expected: moment.Moment): jest.CustomMatcherResult 
    const pass: boolean = received.isSame(expected);
    const message: () => string = () => pass ? "" : `Received moment ($received.toISOString()) is not the same as expected ($expected.toISOString())`;

    return 
      message,
      pass,
    ;
  ,
);

但是,我真的不能让它在我的单元测试中工作...... 当我尝试以下测试代码时:

import moment from "moment";
import "../jest-matchers/moment";

describe("Moment matcher", () => 

  test("should fail", () => 
    const moment1 = moment.utc();
    const moment2 = moment();

    expect(moment1).toBeSameMoment(moment2);
  );

);

...然后我收到以下错误:

error TS2339: Property 'toBeSameMoment' does not exist on type 'JestMatchersShape<Matchers<void, Moment>, Matchers<Promise<void>, Moment>>'.

不过,我不太明白这个错误。例如,这里指的 void 类型是什么?我试过用谷歌搜索它,但并没有真正找到一个好的指南。我确实注意到了这个问题:How to let know typescript compiler about jest custom matchers?,这似乎基本上是重复的,但显然还不够清楚。

我的 tsconfig 中包含 jest 类型

【问题讨论】:

【参考方案1】:

您链接到的另一个问题和答案是正确的,您还可以在 react-testing-library 上的this github comment 中找到一个非常简洁的示例来说明如何扩展 jest。

要为您的代码实施他们的解决方案,只需更改:

declare global 
  namespace jest 
    interface MomentMatchers extends Matchers<moment.Moment> 
      toBeSameMoment: (expected: moment.Moment) => CustomMatcherResult;
    
  

收件人:

declare global 
  namespace jest 
    interface Matchers<R> 
      toBeSameMoment(expected: moment.Moment): CustomMatcherResult;
    
  

【讨论】:

确实,这行得通。谢谢!你能解释一下这个“R”指的是什么吗? &lt;_&gt; 表示 TypeScript 中的泛型,它基本上是要由其他代码填充的类型的占位符。在这个特定的场景中,我猜他们使用R 代表Received,这是有道理的,因为如果你查看@types/jest/index.d.ts,你可以看到他们也使用&lt;E&gt;在 Matchers 上定义的方法中,其中E 是预期值的类型。 好吧,这对我来说开始有些意义了......我有点期望我需要自己提供类型参数,但如果 R​​ 意味着收到,那就解释了。期望参数的类型需要是相同的类型,因此类型可以从expect方法接收到的对象中推断出来。 在 Typescript v4 中 @typescript-eslint/no-namespace 失败并显示 ES2015 module syntax is preferred over custom TypeScript modules and namespaces。有没有比简单地禁用此规则更好的方法?或者只要jest 是全局的,就必须禁用? 你把 jest.d.ts 放在哪里让这个解决方案真正起作用?

以上是关于如何让 Jest 自定义匹配器在打字稿中工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何让打字稿方法回调在 VueJs 中工作?

如何让 CSS 选择器在 Chrome 17 的开发者工具中工作?

带有 Jest 的打字稿 - “ReferenceError:未定义 beforeAll”

将firebase json转换为打字稿数组

如何让 C 语言中的 ANTLR3.5 生成的解析器在 MVS EBCDIC 环境中工作?

为自定义打字稿错误实例实施 instanceof 检查?