// Actual Implementation
import { ModuleToMock} from 'module-to-mock'
const test = new ModuleToMock('value1', 'value2')
test.setUser({ name: 'test', address: 'myTest' })
// test case using jest
import { ModuleToMock} from 'module-to-mock'
jest.mock('module-to-mock')
// constructor response
const mockedModuleResponse = {
setUser: jest.fn(),
}
ModuleToMock.mockImplementation(() => mockedModuleResponse)
const {MockConstructorSpy} = require('../mock-constructor-spy');
const spyCredentialCreation = MockConstructorSpy('./credential-request', 'CredentialRequest', false);
// The import must be done after the call to MockConstructorSpy
import {CredentialRequest} from './credential-request';
it('should catch the constructor call', () => {
const a = new CredentialRequest('a', 'b');
expect(spyCredentialCreation).toHaveBeenCalled();
expect(a.email).toBe('a');
});
/**
* 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 };
});
}
用法示例:
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();
});
8条答案
按热度按时间368yc8dk1#
@gillyb是对的,只是忘了“模拟”
Foo
模块4ngedf3f2#
如果你真的想监视构造函数,你可以这样做:
jei2mxaa3#
我觉得没有官方的办法,我个人是这样做的:
那我就查一下间谍:
2exbekwf4#
来自How to Use Jest to Mock Constructors的引用
efzxgjgh5#
其实还有一个办法:)
甚至在官方文件中也有记载:https://jestjs.io/docs/en/es6-class-mocks#complete-example
下面是您可以如何使用代码执行此操作:
w8biq8rn6#
例如,如果您需要验证传递给构造函数的参数,则不必直接模拟ctor'。
我在ctor的类中创建了一个静态方法。
用
jest.spy.mockImplementation
进行正常的模拟,对数据参数进行一些验证。在ctor'中,我调用这个
checkData
函数,输入我想要的任何输入,特别是ctor'的参数。而且walla,ctor的参数是在不模仿ctor本身的情况下验证的。
50few1ms7#
我创建了一个helper函数来为我的多个类执行此操作:
然后,我对每个要探查其构造函数的类执行以下操作
camsedfj8#
我理解你的观点,我花了一些时间来寻找解决方案。我最终创建了这个代码片段,它可以监视整个类,包括它的构造函数。而且用法也很简单,你可以把这个片段添加到一个文件中,然后在需要的时候导入它。
下面是代码(typescript/ES6):
用法示例:
希望它能对你和其他人有所帮助。