我试图按照Jest文档中的ES6 Class Mocks页来测试TypeScript类Consumer
上的方法。此类实例化一个Provider
对象并对其调用方法,因此我想模拟Provider
类。
目录结构:
.
├── __tests__
│ └── consumers
│ └── Consumer.test.ts
└── js
├── providers
│ └── provider.ts
└── consumers
└── Consumer.ts
provider.ts
:
export class Provider {
constructor() {}
public action(params) {
// do some stuff that we need to mock
return something;
}
}
Consumer.ts
:
import {Provider} from "../providers/provider";
export class Consumer {
private provider: Provider;
constructor() {
this.provider = new Provider();
}
public doSomething() {
const result = this.provider.action(params);
// do something with 'result'
}
}
我的第一次尝试是使用默认的“自动模拟”:
Consumer.test.ts
:
import {Consumer} from "../../js/consumers/Consumer";
jest.mock("../../js/providers/provider");
test("Consumer doSomething", () => {
// a mock Provider will be instantiated in Consumer's ctor:
const consumer = new Consumer();
// however, Provider.action() will return undefined within doSomething()
consumer.doSomething();
});
这证明我可以用模拟代替真正的实现,但是我需要确保Provider.action()
返回一个值,所以接下来我尝试:
// at some point we can make this return something, but first check it works
const mockAction = jest.fn();
jest.mock("../../js/providers/provider", () => {
return jest.fn().mockImplementation(() => {
return {action: mockAction};
});
});
test("Consumer doSomething", () => {
// throws TypeError: provider_1.Provider is not a constructor
const consumer = new Consumer();
consumer.doSomething();
});
无论我如何尝试更改模拟,都无法找到一种解决方案,该解决方案允许我在测试中像往常一样使用Consumer
。我宁愿避免创建“手动模拟”,这样可以使代码库更整洁并在测试之间改变模拟实现。
答案 0 :(得分:0)
您不必在此处使用默认导出。使用命名导出时,您需要创建一个与模块“形状”匹配的模拟。因此,在您的情况下:
const mockAction = jest.fn();
jest.mock("../../js/providers/provider", () => ({
Provider: jest.fn().mockImplementation(() => ({
action: mockAction
}))
));