用玩笑嘲笑打字稿界面

Cut*_*ert 14 mocking typescript jestjs

是否可以用玩笑来模拟打字稿界面?

例如:

import { IMultiplier } from "./IMultiplier";

export class Math {
  multiplier: IMultiplier;

  public multiply (a: number, b: number) {
    return this.multiplier.multiply(a, b);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在测试中:

import { Math } from "../src/Math";
import { IMultiplier } from "../src/IMultiplier";

describe("Math", () => {

    it("can multiply", () => {
        let mathlib = new Math();
        mathlib.multiplier = // <--- assign this property a mock
        let result = mathlib.multiply(10, 2);
        expect(result).toEqual(20);
    });
});
Run Code Online (Sandbox Code Playgroud)

我尝试创建一个模拟对象来通过多种方式满足此要求,但是没有任何效果。例如,为其分配此模拟:

let multiplierMock = jest.fn(() => ({ multiply: jest.fn() }));
Run Code Online (Sandbox Code Playgroud)

将产生类似于以下内容的东西:

Error - Type 'Mock<{ multiply: Mock<{}>; }>' is not assignable to type 'IMultiplier'.
Run Code Online (Sandbox Code Playgroud)

mar*_*aos 19

我创建了一个库,允许您模拟 TypeScript 接口 - https://github.com/marchaos/jest-mock-extended

似乎没有库可以在保持完整类型安全的同时干净利落地做到这一点。它松散地基于这里的讨论 - https://github.com/facebook/jest/issues/7832


Bri*_*ams 9

模拟只需要具有相同的形状接口。

(来自docsTypeScript的核心原则之一是类型检查着重于值的形状。这有时被称为“鸭子类型”或“结构子类型化”。

所以mathlib.multiplier只需要分配给一个符合IMultiplier

我猜IMultiplier从该示例看起来像这样:

interface IMultiplier {
  multiply(a: number, b: number): number
}
Run Code Online (Sandbox Code Playgroud)

因此,通过将相关行更改为此示例测试可以正常工作:

mathlib.multiplier = {
  multiply: jest.fn((a, b) => a * b)
};
Run Code Online (Sandbox Code Playgroud)

  • 尽管从技术上来说,模拟只需要与界面具有相同的形状是正确的,但这没有抓住重点。重点是有一种方便的方法来生成给定接口的模拟,这样开发人员就不必手动创建模拟类,只是为了每次需要运行时从十几个方法中删除一个函数一个测试。 (28认同)
  • 更不用说根据您项目的 ESLint 设置,此解决方案可能不起作用。 (3认同)

小智 5

试用moq.ts库。

import {Mock} from "moq.ts";

const multiplier = new Mock<IMultiplier>()
   .setup(instance => instance.multiply(3, 4))
   .returns(12)
   .object();

let mathlib = new Math();
mathlib.multiplier = multiplier;
Run Code Online (Sandbox Code Playgroud)

  • OP 特别询问如何在 Jest 中实现这一点。虽然起订量可能是一个可行的选择,但这并不是OP所要求的。 (3认同)