【问题标题】:How to get a Jest custom matcher working in typescript?如何让 Jest 自定义匹配器在打字稿中工作?
【发布时间】: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 类型

【问题讨论】:

    标签: typescript jestjs momentjs matcher ts-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 放在哪里让这个解决方案真正起作用?
    猜你喜欢
    • 2020-04-17
    • 2022-10-20
    • 1970-01-01
    • 2021-07-19
    • 2016-06-11
    • 1970-01-01
    • 2021-02-07
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多