简体   繁体   English

当组件的方法,从componentDidMount称为间谍,间谍不会被调用

[英]When spying on component method, called from componentDidMount, the spy is never called

In a React component I have 在React组件中,我有

export default class MyComp extends Component {
  ...
  componentDidMount() {
    this.customFunc();
  }
  customFunc = () => {
    // ..
  }
  ...
}

And when I try to test this method with Jest and Enzyme like this: 当我尝试像这样用Jest和Enzyme测试这种方法时:

it('Should call customFunc on mount', () => {
  const MyCompInstance = mount(<MyComp {...props} >).instance();
  const spy = jest.spyOn(MyCompInstance, 'customFunc');

  expect(spy).toHaveBeenCalled();
});

it fails with Expected mock function to have been called, but it was not called. 它因Expected mock function to have been called, but it was not called.Expected mock function to have been called, but it was not called.失败Expected mock function to have been called, but it was not called.

The funny thing is that if I put console.log() in componentDidMount and in custsomFunc - they get called. 有趣的是,如果我将console.log()放在componentDidMountcustsomFunc ,它们会被调用。 What am I doing wrong? 我究竟做错了什么?

PS: I tried with forceUpdate on the instance, right before the expect, but I still get the same error. PS:我尝试在实例上使用forceUpdate ,就在期望值之前,但是我仍然遇到相同的错误。

it fails with Expected mock function to have been called, but it was not called. 它因Expected mock function to have been called, but it was not called.Expected mock function to have been called, but it was not called.失败Expected mock function to have been called, but it was not called.

The funny thing is that if I put console.log() in componentDidMount and in custsomFunc - they get called. 有趣的是,如果我将console.log()放在componentDidMountcustsomFunc ,它们会被调用。

Calling mount renders the component and componentDidMount gets called as part of that process, which in turn calls customFunc . 调用mount会渲染component,而componentDidMount会在该过程中被调用,而后者又会调用customFunc

The spy then gets created on customFunc but by that time it is too late since componentDidMount and customFunc have already run as part of mount and the test fails with the spy reporting that it was not called. 然后在customFunc创建spy ,但是那时已经太晚了,因为componentDidMountcustomFunc已经作为mount一部分运行,并且测试失败,并报告spy没有被调用。


What am I doing wrong? 我究竟做错了什么?

You need to create the spy on customFunc before it gets called. 您需要先在customFunc上创建spycustomFunc 才能对其进行调用。

This is very difficult the way the code is currently written since customFunc is implemented as an instance property . 由于customFunc是作为实例属性实现的,因此当前编写代码的方式非常困难。

Because it is an instance property it won't exist until the instance exists but the instance gets created during the rendering process which ends up calling componentDidMount . 因为它是一个实例属性,所以它在实例存在之前不会存在,但是在渲染过程中会创建该实例,最终调用componentDidMount

In other words, you need an instance to spy on customFunc , but customFunc gets called as part of creating the instance. 换句话说,您需要一个实例来监视customFunc ,但是customFunc在创建实例时会被调用。

In this scenario the only way to check if customFunc is called when componentDidMount runs is to call it again after the instance has been created and the component has rendered, which is kind of a hack: 在这种情况下,检查componentDidMount运行时是否检查customFunc的唯一方法是在创建实例并呈现组件之后再次调用它,这有点像hack:

import * as React from 'react';
import { mount } from 'enzyme';

class MyComp extends React.Component {
  componentDidMount() {
    this.customFunc();
  }
  customFunc = () => { }  // instance property
  render() { return <div/> }
}

it('Should call customFunc on mount', () => {
  const instance  = mount(<MyComp />).instance();
  const spy = jest.spyOn(instance, 'customFunc');  // spy on customFunc using the instance
  instance.componentDidMount();  // call componentDidMount again...kind of a hack
  expect(spy).toHaveBeenCalled();  // SUCCESS
});

The alternative is to implement customFunc as a class method . 另一种方法是将customFunc实现为类方法

If customFunc is a class method then it will exist on the prototype of the class which allows you to create a spy on customFunc before the instance gets created during the render process in mount : 如果customFunc是一个类方法,则它将存在于该类的prototype上,允许您在mount的渲染过程中创建实例之前customFunc上创建间谍:

import * as React from 'react';
import { mount } from 'enzyme';

class MyComp extends React.Component {
  componentDidMount() {
    this.customFunc();
  }
  customFunc() { }  // class method
  render() { return <div/> }
}

it('Should call customFunc on mount', () => {
  const spy = jest.spyOn(MyComp.prototype, 'customFunc');  // spy on customFunc using the prototype
  const wrapper = mount(<MyComp />);
  expect(spy).toHaveBeenCalled();  // SUCCESS
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM