用玩笑嘲笑打字稿界面

时间:2018-08-31 20:27:55

标签: typescript mocking jestjs

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

例如:

import { IMultiplier } from "./IMultiplier";

export class Math {
  multiplier: IMultiplier;

  public multiply (a: number, b: number) {
    return this.multiplier.multiply(a, b);
  }
}

然后进行测试:

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

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

let multiplierMock = jest.fn(() => ({ multiply: jest.fn() }));

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

Error - Type 'Mock<{ multiply: Mock<{}>; }>' is not assignable to type 'IMultiplier'.

4 个答案:

答案 0 :(得分:6)

该模拟只需要与接口具有相同的 shape

(摘自docs TypeScript的核心原则之一是类型检查着重于值的形状,有时也称为“鸭子类型”或“结构子类型化”。

因此,mathlib.multiplier仅需要分配给符合IMultiplier的对象。

我猜示例中的IMultiplier看起来像这样:

interface IMultiplier {
  multiply(a: number, b: number): number
}

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

mathlib.multiplier = {
  multiply: jest.fn((a, b) => a * b)
};

答案 1 :(得分:5)

试用moq.ts库。

if __name__ == "__main__":
    t = DummyThread()
    t.start()
    t.join()
    print("Exit")

答案 2 :(得分:1)

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

似乎没有库在保持完全类型安全的同时干净地进行此操作。它大致基于此处的讨论-https://github.com/facebook/jest/issues/7832

答案 3 :(得分:0)

如果 multiplier 属性是 protected 属性,@Brian Adams 的答案不起作用
在这种情况下,我们可以这样做:
目标类别

import { IMultiplier } from "./IMultiplier";

export class Math {
  protected multiplier: IMultiplier;

  public multiply (a: number, b: number) {
    return this.multiplier.multiply(a, b);
  }
}

单元测试

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

describe("Math", () => {
    class DummyMultiplier implements IMultiplier {
        public multiply(a, b) {
            // dummy behavior
            return a * b;
        }
    }

    class TestableMathClass extends Math {
        constructor() {
            super();
            // set the multiplier equal to DummyMultiplier
            this.multiplier = new DummyMultiplier();
        }
    }

    it("can multiply", () => {
        // here we use the right TestableMathClass
        let mathlib = new TestableMathClass();
        let result = mathlib.multiply(10, 2);
        expect(result).toEqual(20);
    });

    it("can multiply and spy something...", () => {
        // with spy we can verify if the function was called
        const spy = jest
            .spyOn(DummyMultiplier.prototype, 'multiply')
            .mockImplementation((_a, _b) => 0);

        let mathlib = new TestableMathClass();
        let result = mathlib.multiply(10, 2);
        expect(result).toEqual(20);
        expect(spy).toBeCalledTimes(1);
    });
});

如果您使用private 属性,也许您可以注入该属性。因此,在单元测试中,您还可以创建一个虚拟行为并注入它。