【问题标题】:Jest / Enzyme can't mock class propertyJest / Enzyme 不能模拟类属性
【发布时间】:2018-03-28 20:56:00
【问题描述】:

我目前正在使用 Jest an Enzyme 为 React 组件编写测试。当我必须模拟一个用箭头语法编写的类属性函数时,我被卡住了:未应用模拟。

这里是测试组件的摘录:

class MaClass extends React.Component {
  ...
  componentWillMount () {
    this.getNotifications()
  }
  getNotifications = () => {
    axios.get(window.Routing.generate(
      'api_notifications_get_collection'
    ), {
      headers: {
        'Accept': 'application/json'
      }
    }).then(response => {
      this.setState({
        notifications: response.data
      })
    }).catch(error => {
      console.log('Error : ', error)
    })
  }
  ...
}

这是测试:

import React from 'react'
import { configure, shallow } from 'enzyme'
import Adapter from 'enzyme-adapter-react-15'

import NotificationsComponent from './NotificationsComponent'

configure({adapter: new Adapter()})

describe('Testing NotificationsComponent', () => {
  /**
   * This should call getNotifications
   */
  test('getNotifications should be called', () => {
    let wrapper = shallow(<NotificationsComponent />)
    const getMock = jest.fn()
    wrapper.instance().getNotifications = getMock
    wrapper.update()
    expect(getMock).toHaveBeenCalled()
  })
})

就阅读而言,这是常规方法的正确方法。但是用箭头语法写的类属性函数好像不能这样mock。

我的终端抛出一个关于被测组件方法内部的错误:

TypeError: Cannot read property 'generate' of undefined

这意味着mock没有通过。

谁能指出我的错误在哪里?谢谢。

【问题讨论】:

    标签: reactjs jestjs enzyme


    【解决方案1】:

    您为此使用了错误的生命周期挂钩。 componentWillMount 被称为“内部”shallow(&lt;NotificationsComponent /&gt;)。因此,原始的getNotifications 已被调用。

    wrapper.update() 强制重新渲染并且不重新安装组件,因此您对模拟的分配不会达到预期的效果。

    【讨论】:

    • 我使用mount 也没有运气。
    • mount 将重置您的组件...您可以将 getNotifications 作为 prop 传入,就像这里的 stackoverflow.com/questions/41598559/… 一样。如果您正在使用 redux 或其他状态管理,这无论如何都是有益的。
    • 实际上我不确定这是否符合我的需求,因为在它的示例中,他定义了this.props.fetch('data')。我不是在测试道具,而是在测试类属性,就像我之前给出的示例一样:getNotifications = () =&gt; {...}。这里重要的部分是它使用= () =&gt;
    【解决方案2】:

    问题是没有好的方法来模拟作为箭头函数的类属性。到目前为止,我发现的最佳解决方法是将类属性移动到类方法并将该方法绑定到构造函数中。

    constructor(props) {
        super(props);
        this.getNotifications = this.getNotifications.bind(this);
    }
    
    getNotifications() {...}
    

    那么在你的测试中你将能够正确使用jest.spyOn():

    const spy = jest.spyOn(MaClass.prototype, 'getNotifications');
    

    这里有一些关于它的附加信息: https://remarkablemark.org/blog/2018/06/13/spyon-react-class-method/

    希望有帮助!

    【讨论】:

    • 你是对的。由于当时无法解决的流类型问题,我从 custructor 绑定中移出。
    猜你喜欢
    • 2019-05-12
    • 2019-08-28
    • 2019-01-29
    • 2021-10-31
    • 2019-06-22
    • 1970-01-01
    • 2019-10-27
    • 2018-06-04
    • 2020-02-02
    相关资源
    最近更新 更多