【问题标题】:React test with enzyme TypeError: Cannot read property 'state' of undefined使用酶 TypeError 进行反应测试:无法读取未定义的属性“状态”
【发布时间】:2018-03-06 06:56:57
【问题描述】:

我正在尝试使用酶浅渲染对组件进行单元测试。尝试测试组件的状态 activeTab 并抛出 TypeError: Cannot read property state。我的组件手风琴。手风琴组件jsx代码

 class Accordion extends Component {
    constructor(props) {
        super(props)
        this.state = {
            activeTab: 0
        }
    }

    static defaultProps = {
        tabs: [{title: 'Status'}, {title: 'Movement'}]
    }

    render() {
        const { tabs } = this.props
            , { activeTab } = this.state
        return (
            <div className={`accordion`}>
                {tabs.map((t, i) => {
                    const activeClass = activeTab === i ? `accordion--tab__active` : ''
                    return(
                        <section key={i} className={`accordion--tab ${activeClass}`}>
                            <header className={`accordion--header`}>
                                <h4 className={`accordion--title`}>
                                    <button onClick={() => {this._selectAccordion(i)}}>{t.title}</button>
                                </h4>
                            </header>
                            <div className="accordion--content">
                                {t.title}
                                Content
                            </div>
                        </section>
                    )
                })}
            </div>
        )
    }
    _selectAccordion = activeTab => {this.setState({activeTab})}
}

export default Accordion

Accordion.react.test.js

import { shallow } from 'enzyme'
import Accordion from './components/Accordion'

test('Accordion component', () => {
    const component = shallow(<Accordion name={`Main`}/>)
    expect(component.state('activeTab')).equals(0)
})

【问题讨论】:

  • 测试在我的电脑上运行良好,但我必须将.equals(0) 更改为.toEqual(0)。也许您可以分享更多调试信息,例如酶/节点版本,或者至少粘贴完整的错误消息 - 您粘贴的肯定只是消息的一半。
  • 你在 Jsx 文件中导入了 REACT 吗?
  • 是的,我在 jsx 文件中导入 React。
  • 你说的是jsx文件,但是在Accordian.react.test.js中你是import Accordion from './components/Accordion.js,这是一个js文件而不是jsx文件。你确定文件扩展名是正确的吗?无论如何,您不需要将文件扩展名放在文件路径中。
  • 这是一个错误,我已经修复了它,但在我的实际项目中它只是Accordion

标签: javascript reactjs enzyme jestjs


【解决方案1】:

这可能是一个范围界定问题。使用 React 中的事件处理程序,您必须将构造函数中的事件处理程序绑定到“this”。以下是来自 React 的 docs 的一些信息:

在 JSX 回调中你必须小心 this 的含义。在 JavaScript,类方法默认不绑定。如果你忘记 绑定 this.handleClick 并将其传递给 onClick,这将是未定义的 当函数被实际调用时。

这不是 React 特有的行为;它是功能的一部分 在 JavaScript 中工作。一般来说,如果你引用一个没有()的方法 在它之后,例如 onClick={this.handleClick},你应该绑定它 方法。

class Accordion extends Component {
    constructor(props) {
        super(props)
        this.state = {
            activeTab: 0
        }

        // This binding is necessary to make `this` work in the callback
        this._selectAccordion = this._selectAccordion.bind(this);
    }

    static defaultProps = {
        tabs: [{title: 'Status'}, {title: 'Movement'}]
    }

        _selectAccordion(activeTab){
            this.setState({activeTab : activeTab})
        }

    render() {
        const { tabs } = this.props,
        { activeTab } = this.state
        return (
            <div className={`accordion`}>
                {tabs.map((t, i) => {
                    const activeClass = activeTab === i ? `accordion--tab__active` : ''
                    return(
                        <section key={i} className={`accordion--tab ${activeClass}`}>
                            <header className={`accordion--header`}>
                                <h4 className={`accordion--title`}>
                                    <button onClick={() => {this._selectAccordion(i)}}>{t.title}</button>
                                </h4>
                            </header>
                            <div className="accordion--content">
                                {t.title}
                                Content
                            </div>
                        </section>
                    )
                })}
            </div>
        )
    }

}

【讨论】:

  • 请不要使用绑定,如果你想将任何东西绑定到任何地方使用箭头函数。 Bind 非常非常慢,如果您知道 V8 的工作原理,您应该知道这一点。
【解决方案2】:

您的测试应该验证组件的工作方式,而不是“如何更改状态”。你需要将新的 props 扔到你的组件中并得到一个结果,结果是预期的。

我已经用快照测试了我的组件

这是我当前项目的一个例子

describe('<Component />', () => {
  it('Page rendered', () => {
    const rendered = renderComponent({
      ...testProps,
      loadDataList,
      loading: true,
    });

    expect(rendered).toMatchSnapshot();
  });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2017-12-14
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    相关资源
    最近更新 更多