如何使用 Jest 监视方法调用?
Posted
技术标签:
【中文标题】如何使用 Jest 监视方法调用?【英文标题】:How can I use Jest to spy on a method call? 【发布时间】:2017-08-31 21:15:12 【问题描述】:我最近想测试一些自定义方法是否在 React 组件的 componentDidMount
方法中被有条件地调用。
componentDidMount()
if (this.props.initOpen)
this.methodName();
我使用 Jest 作为我的测试框架,其中包括用于模拟/间谍的 jest.fn()
。我已经读到,通过执行以下操作,使用 Sinon 进行测试是相当简单的:
sinon.spy(Component.prototype, "methodName");
const wrapper = mount(<Component ...props />);
expect(wrapper.instance().methodName).toHaveBeenCalled();
我正在尝试像这样用 Jest 重新创建它:
Component.prototype.methodName = jest.fn();
const wrapper = mount(<Component ...props />);
expect(wrapper.instance().methodName).toHaveBeenCalled();
此代码失败并抛出以下错误:
jest.fn() value must be a mock function or spy.
Received:
function: [Function bound mockConstructor]
是否可以使用 Jest 测试此功能?如果有,怎么做?
【问题讨论】:
【参考方案1】:关键是在对象的prototype
上使用笑话spyOn
方法。应该是这样的:
const spy = jest.spyOn(Component.prototype, 'methodName');
const wrapper = mount(<Component ...props />);
wrapper.instance().methodName();
expect(spy).toHaveBeenCalled();
如在此处找到,例如:Test if function is called react and enzyme
请注意 最好在每次测试运行后清除间谍功能
let spy
afterEach(() =>
spy.mockClear()
)
https://facebook.github.io/jest/docs/en/jest-object.html#jestclearallmocks
【讨论】:
谢谢!看起来这只是几个月前在 19.0.0 中发布的。不敢相信我在文档中跳过了它。 它会真正调用组件中的methodName()
函数还是只是伪造它?
来自文档:“注意:默认情况下,jest.spyOn 也调用了 spy 方法。” facebook.github.io/jest/docs/en/…
如果<Component ...props />
用<Provider>
包裹怎么办,这会起作用吗?我收到了Cannot read property '_isMockFunction' of undefined'
。不知道是不是因为上面的原因。
对我来说,您似乎在监视一种不存在的方法,这就是您获得 Cannot read property '_isMockFunction' of undefined'
的原因。【参考方案2】:
我知道它有点晚了,但我遇到了这个问题并建议测试componentDidMount
启动对嵌套方法的调用,你的测试应该看起来像这样:
模块
componentDidMount()
if (this.props.initOpen)
this.methodName();
测试 - 良好
it('should call methodName during componentDidMount', () =>
const methodNameFake = jest.spyOn(MyComponent.prototype, 'methodName');
const wrapper = mount(<MyComponent ...props />);
expect(methodNameFake).toHaveBeenCalledTimes(1);
);
如果您调用componentDidMount
,那么通过componentDidMount
调用methodName
的断言更有效。
测试 - 不好
it('should call methodName during componentDidMount', () =>
const spy = jest.spyOn(Component.prototype, 'methodName');
const wrapper = mount(<Component ...props />);
wrapper.instance().methodName();
expect(spy).toHaveBeenCalled();
通过这样编写测试 - 您调用该方法,然后断言它已被调用。它当然会给你刚才调用它。
【讨论】:
这些测试都不适合我,根本无法通过 您是否传递了组件所需的所有道具? 终于让它工作了,需要为它创建一个实例并在我的间谍上强制更新。【参考方案3】:如果您尝试测试在 componentDidMount
上调用的 public
方法(如果您使用的是 TypeScript),则需要显式调用 instance
的 componentDidMount
方法调用,因为直到组件实例化后才定义公共方法。
要测试这样的东西:
代码
public componentDidMount()
if (this.props.initOpen)
this.methodName();
public methodName = () =>
// some code here
测试
it('should call methodName during componentDidMount', () =>
const wrapper = mount(<MyComponent ...props />);
const instance = wrapper.instance();
jest.spyOn(instance, 'methodName')
expect(instance.methodName).toHaveBeenCalled();
);
【讨论】:
【参考方案4】:const toastMethodSpy = jest.spyOn(sharedMockedOTPComponent, 'toast')
sharedMockedOTPComponent.handleResendOtpFailure(networkError)
//hide loader
expect(sharedMockedOTPComponent.state.showLoader).toBe(false)
//error message in toast should have been shown
expect(toastMethodSpy).toHaveBeenCalledTimes(1)
【讨论】:
以上是关于如何使用 Jest 监视方法调用?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jest.spyOn 测试 RTKQuery 端点
如何使用 Jest 在 NestJS 的提供者中模拟和监视“mongoose.connect”