如何使用 Jest 监视方法调用?

IT技术 javascript reactjs testing jestjs enzyme
2021-02-25 17:49:25

我最近想测试一些自定义方法是否在componentDidMountReact 组件的方法中被有条件地调用

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 测试此功能?如果是这样,如何?

4个回答

关键是spyOn在对象的prototype. 应该是这样的:

const spy = jest.spyOn(Component.prototype, 'methodName');
const wrapper = mount(<Component {...props} />);
wrapper.instance().methodName();
expect(spy).toHaveBeenCalled();

如此处所见,例如:测试函数是否称为react和酶

请注意 ,在每次测试运行后清除间谍功能也是最佳做法

let spy

afterEach(() => {
  spy.mockClear()
})

https://facebook.github.io/jest/docs/en/jest-object.html#jestclearallmocks

谢谢!看起来它刚刚在 19.0.0 中出现,就在几个月前。不敢相信我在文档中跳过了它。
2021-04-22 17:49:25
它会实际调用methodName()Component 中函数还是只是伪造它?
2021-04-30 17:49:25
如果<Component {...props} />用 a 包裹怎么办<Provider>,这会起作用吗?我得到一个Cannot read property '_isMockFunction' of undefined'. 不确定是不是因为上述原因。
2021-05-02 17:49:25
来自文档:“注意:默认情况下,jest.spyOn 也会调用 spied 方法。” facebook.github.io/jest/docs/en/...
2021-05-07 17:49:25
在我看来,您似乎在监视一种不存在的方法,这就是为什么您获得Cannot read property '_isMockFunction' of undefined'.
2021-05-19 17:49:25

我知道它有点晚了,但我遇到了这个,并建议测试componentDidMount启动对您的嵌套方法的调用,您的测试应该类似于:

module

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那么methodName通过调用调用的断言componentDidMount更有效。

测试 - 差

it('should call methodName during componentDidMount', () => {
    const spy = jest.spyOn(Component.prototype, 'methodName');
    const wrapper = mount(<Component {...props} />);
    wrapper.instance().methodName();
    expect(spy).toHaveBeenCalled();
}

通过像这样编写测试 - 您调用该方法,然后断言它已被调用。这当然会给你打电话。

您是否传递了组件所需的所有道具?
2021-05-09 17:49:25
终于让它工作了,需要为它创建一个实例并在我的间谍上强制更新。
2021-05-15 17:49:25
这些测试都不适合我,根本无法通过
2021-05-21 17:49:25

如果您尝试测试public被调用的方法componentDidMount(如果您使用的是 TypeScript),则需要显式调用instancecomponentDidMount方法调用,因为公共方法直到组件实例化后才定义。

要测试这样的事情:

代码

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();
});
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)