当监视从 componentDidMount 调用的组件方法时,永远不会调用该间谍 [英] When spying on component method, called from componentDidMount, the spy is never called

查看:19
本文介绍了当监视从 componentDidMount 调用的组件方法时,永远不会调用该间谍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 React 组件中

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

当我尝试用 Jest 和 Enzyme 测试这种方法时:

it('应该在挂载时调用 customFunc', () => {const MyCompInstance = mount(<MyComp {...props} >).instance();const spy = jest.spyOn(MyCompInstance, 'customFunc');期望(间谍).toHaveBeenCalled();});

它失败了,预期的模拟函数已经被调用,但它没有被调用.

有趣的是,如果我将 console.log() 放在 componentDidMountcustsomFunc 中 - 它们会被调用.我做错了什么?

PS:我在实例上尝试了 forceUpdate,就在预期之前,但我仍然遇到相同的错误.

解决方案

它失败了,预期的模拟函数已经被调用,但它没有被调用.

有趣的是,如果我将 console.log() 放在 componentDidMountcustsomFunc 中 - 它们会被调用.

调用 mount 渲染组件,并且 componentDidMount 作为该过程的一部分被调用,然后调用 customFunc.

spy 然后在 customFunc 上创建,但到那时已经太晚了,因为 componentDidMountcustomFunc已经作为 mount 的一部分运行并且测试失败,spy 报告它没有被调用.


<块引用>

我做错了什么?

您需要在 customFunc 上创建 spy 在它被调用之前.

这是目前编写代码的方式非常困难,因为 customFunc 是作为一个实例属性实现的.

因为它是一个实例属性,所以在实例存在之前它不会存在,但是在渲染过程中创建了实例,最终调用 componentDidMount.

换句话说,您需要一个实例来监视 customFunc,但是 customFunc 在创建实例的过程中被调用.

在这种情况下,检查 componentDidMount 运行时是否调用 customFunc 的唯一方法是在创建实例后再次调用它并且组件已经呈现,这是一种黑客:

import * as React from 'react';从'酶'导入{安装};class MyComp 扩展了 React.Component {componentDidMount() {this.customFunc();}customFunc = () =>{ }//实例属性render() { 返回 

}}it('应该在挂载时调用 customFunc', () => {const instance = mount().instance();const spy = jest.spyOn(instance, 'customFunc');//使用实例监视 customFuncinstance.componentDidMount();//再次调用 componentDidMount ......有点像黑客期望(间谍).toHaveBeenCalled();//成功});


另一种方法是将 customFunc 实现为类方法.

如果 customFunc 是一个类方法,那么它将存在于该类的 prototype 上,这允许您在 customFunc 上创建间谍em>before 在 mount 渲染过程中创建实例:

import * as React from 'react';从'酶'导入{安装};class MyComp 扩展了 React.Component {componentDidMount() {this.customFunc();}customFunc() { }//类方法render() { 返回 

}}it('应该在挂载时调用 customFunc', () => {const spy = jest.spyOn(MyComp.prototype, 'customFunc');//使用原型监视 customFuncconst wrapper = mount();期望(间谍).toHaveBeenCalled();//成功});

In a React component I have

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

And when I try to test this method with Jest and Enzyme like this:

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.

The funny thing is that if I put console.log() in componentDidMount and in custsomFunc - they get called. What am I doing wrong?

PS: I tried with forceUpdate on the instance, right before the expect, but I still get the same error.

解决方案

it fails with 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.

Calling mount renders the component and componentDidMount gets called as part of that process, which in turn calls 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.


What am I doing wrong?

You need to create the spy on customFunc before it gets called.

This is very difficult the way the code is currently written since customFunc is implemented as an instance property.

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.

In other words, you need an instance to spy on customFunc, but customFunc gets called as part of creating the instance.

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:

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.

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:

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

这篇关于当监视从 componentDidMount 调用的组件方法时,永远不会调用该间谍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆