是否可以用玩笑来模拟打字稿界面?
例如:
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'.
答案 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
属性,也许您可以注入该属性。因此,在单元测试中,您还可以创建一个虚拟行为并注入它。