You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试传递函数作为Props的Jest组件时遭遇TypeError问题求助

解决Jest测试中TypeError: this.props.isLoading is not a function的问题

你遇到的这个报错主要来自两个核心问题:测试代码的用法错误,以及Container组件里方法的this绑定问题,咱们一步步来捋清楚并解决:

1. 先搞定测试代码的关键错误

看你的Item.test.js,这里有两个明显的问题:

  • 错误导入类方法:changeIsLoading是Container类的实例方法,不是单独导出的独立函数,你直接import changeIsLoading from '../containers/Container'拿到的其实是Container类本身,根本不是目标方法。
  • 传递了函数执行结果而非函数本身:你写的isLoading={changeIsLoading(false)}会立即执行这个方法,把返回的布尔值false传给了isLoading props——这就导致Item组件里调用this.props.isLoading()时,面对的是一个布尔值而非函数,自然会报错。

正确的测试姿势(两种可选)

方式一:单元测试Item组件(推荐)

直接给Item传递一个Jest模拟函数,专注测试Item自身的逻辑:

// Item.test.js
import React from 'react';
import Item from './Item'; // 确保导入的是Item组件
import { mount } from 'enzyme';

describe('Item Component', () => {
  it('renders correctly and triggers isLoading prop as expected', () => {
    // 创建模拟函数,用来追踪是否被调用
    const mockIsLoading = jest.fn();
    const testStyles = {}; // 定义你的测试用样式

    const tree = mount(
      <Item 
        className="item" 
        isLoading={mockIsLoading} 
        styles={testStyles} 
      />
    );

    // 这里可以模拟Item里触发isLoading的操作(比如点击按钮)
    // tree.find('.trigger-btn').simulate('click');

    // 验证模拟函数是否被正常调用
    expect(mockIsLoading).toHaveBeenCalled();
    expect(tree).toMatchSnapshot();
  });
});

方式二:集成测试Container与Item的交互

如果想测试两者的联动逻辑,直接渲染完整的Container组件即可:

// Container.test.js
import React from 'react';
import Container from './Container';
import { mount } from 'enzyme';

describe('Container Component', () => {
  it('updates state when Item triggers isLoading', () => {
    const testStyles = {};
    const tree = mount(<Container styles={testStyles} />);

    // 获取Item组件并调用它的isLoading prop
    const itemComponent = tree.find('Item');
    itemComponent.props().isLoading(true);

    // 验证Container的状态是否正确更新
    expect(tree.state('isLoading')).toBe(true);
    expect(tree).toMatchSnapshot();
  });
});

2. 修复Container组件的this绑定问题

你的Container里changeIsLoading方法没有绑定this,就算测试代码改对了,Item调用这个方法时也会因为this指向错误导致setState报错。这里有三种常用的解决方式:

方式一:构造函数内绑定this

// Container.js
import React, { Component } from 'react';
import Item from './Item';

class Container extends Component {
  constructor() {
    super();
    this.state = {
      isLoading: false,
    };
    // 绑定this到当前类实例
    this.changeIsLoading = this.changeIsLoading.bind(this);
  }

  changeIsLoading(bool) {
    this.setState({ isLoading: bool });
  }

  render() {
    return (
      <div className="container">
        <Item 
          className="item" 
          isLoading={this.changeIsLoading} 
          styles={this.props.styles} 
        />
      </div>
    );
  }
}

方式二:用箭头函数定义类方法

箭头函数会自动绑定当前类的this,写法更简洁:

// Container.js
import React, { Component } from 'react';
import Item from './Item';

class Container extends Component {
  constructor() {
    super();
    this.state = {
      isLoading: false,
    };
  }

  // 箭头函数自动绑定this
  changeIsLoading = (bool) => {
    this.setState({ isLoading: bool });
  }

  render() {
    return (
      <div className="container">
        <Item 
          className="item" 
          isLoading={this.changeIsLoading} 
          styles={this.props.styles} 
        />
      </div>
    );
  }
}

方式三:render中用箭头函数传递(不推荐频繁使用)

这种方式每次render都会创建新函数,可能导致Item不必要重渲染,适合简单场景:

// Container.js
import React, { Component } from 'react';
import Item from './Item';

class Container extends Component {
  constructor() {
    super();
    this.state = {
      isLoading: false,
    };
  }

  changeIsLoading(bool) {
    this.setState({ isLoading: bool });
  }

  render() {
    return (
      <div className="container">
        <Item 
          className="item" 
          isLoading={(bool) => this.changeIsLoading(bool)} 
          styles={this.props.styles} 
        />
      </div>
    );
  }
}

总结一下:先把测试代码里的props传递逻辑改对,确保给isLoading传的是函数而非执行结果;再解决Container里方法的this绑定问题,这样就能正常运行啦。

内容的提问来源于stack exchange,提问作者jak111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:44:42