[英]How to spyOn class instantiated on constructor in jest
I have the next code:我有下一个代码:
async function(paramA?: string): Promise<void> {
if (paramA === undefined) {
paramA = this.randomString();
}
this.funnel.loginFunnel(Status.Pending);
await this.tracker.flush();
this.service.call(this.name, paramA, code);
}
And I want test that loginFunnel is called with status pending, and the service is call with the paramA, but this classes are initialized in constructor:我想测试 loginFunnel 被调用时状态未决,并且服务是用 paramA 调用的,但是这个类是在构造函数中初始化的:
constructor(params: Params) {
this.tracker = new Tracker(params);
this.service = new Service(params, this.tracker);
}
So how I can spy on with jest?, this is only javascript, not React or similar.那么我怎么能开玩笑地监视呢?这只是 javascript,不是 React 或类似的。
I try a lot of things, but I don't know how do...我尝试了很多东西,但我不知道该怎么做...
The last try was this, import Tracker class from his path...最后一次尝试是这样的,从他的路径中导入 Tracker class ...
jest.mock('../tracker');
service.call();
expect(Tracker).toHaveBeenCalledTimes(1);
But I got this answer from test:但我从测试中得到了这个答案:
expect(received).toHaveBeenCalledTimes(expected)
Matcher error: received value must be a mock or spy function
Received has type: function
Received has value: [Function Tracker]
I understand your point.我明白你的意思。 It's complex and I ended up creating this code snippet, which can spyOn an entire class, including its constructors.它很复杂,我最终创建了这个代码片段,它可以监视整个 class,包括它的构造函数。 And the usage is also somehow simple, you can add this snippet to a file and import it whenever you need.而且用法也很简单,您可以将此代码段添加到文件中并在需要时导入它。
Here is the code (typescript/ES6):这是代码(打字稿/ES6):
/**
* spyOn references to classes. Use it with spyOnClass
*/
export const classSpy: any = {};
/**
* Utility to Spy On all class methods. Not including the constructor
* @returns a spyOn references to all the class methods
* includes the methods mockClear and mockReset as convenience
* to trigger the respective method for all the spies
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function spyOnClassMethods(proto: any): any {
const properties = Object.getOwnPropertyNames(proto);
const spyHolder: any = {};
for (const i in properties) { spyHolder[properties[i]] = jest.spyOn(proto, properties[i]); }
spyHolder.mockClear = (): void => { for (const i in properties) { spyHolder[properties[i]].mockClear(); } };
spyHolder.mockReset = (): void => { for (const i in properties) { spyHolder[properties[i]].mockReset(); } };
return spyHolder;
}
// To attend jest.mock problems, the should start with 'mock'
const mocksSpyOnClassMethods = spyOnClassMethods;
/**
* Utility to Spy On all class methods and its constructor.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function spyOnClass(mockModuleName: string, mockClassName: string): any {
classSpy[mockClassName] = {};
jest.mock(mockModuleName, () => {
const module = jest.requireActual(mockModuleName) as any;
const mock = {};
classSpy[mockClassName] = mocksSpyOnClassMethods(module[mockClassName].prototype);
mock[mockClassName] = jest.fn().mockImplementation(
(...args: any[]) => {
const instance = new module[mockClassName](...args);
classSpy[mockClassName].constructor = mock[mockClassName];
return instance;
}
);
return { ...module, ...mock };
});
}
Usage example:使用示例:
import { classSpy, spyOnClass } from './mock-utils';
// If you import ClassName, this must come before the import.
spyOnClass('module-name', 'ClassName');
import { ClassName } from 'module-name';
test('this', () => {
doSomethingThatUsesClassName();
expect(classSpy.ClassName.constructor).toHaveBeenCalled();
expect(classSpy.ClassName.someMethod).toHaveBeenCalled();
});
Hope it can help you and others.希望它可以帮助你和其他人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.