【问题标题】:How to spy componentWillMount using jest and enzyme如何使用 jest 和酶来监视 componentWillMount
【发布时间】:2017-01-11 18:54:25
【问题描述】:

我正在尝试测试是否调用了 componentWillMount,为此我的测试是

test('calls `componentWillMount` before rendering', () => {
  let fn = jest.fn(SomeComponent.prototype.componentWillMount)
  mount(<SomeComponent />)
  expect(fn).toHaveBeenCalled()
})

但是即使调用了 componentWillMount 方法,测试也没有通过。 我在这里错过了什么?

【问题讨论】:

    标签: unit-testing reactjs jestjs enzyme


    【解决方案1】:

    我不知道其他答案是否对您的问题有所帮助,但您不需要测试 componentWillMount。 React 应该已经为您完成了该测试。

    与您的测试更相关的是测试您在该方法中为组件添加的功能或操作。

    如果您要进行一些 API 调用、运行基于 props 的函数或其他任何东西,那么您应该进行测试。模拟componentWillMount 触发的函数/动作/代码,并对其做出断言和期望。

    例子:

    组件:

    class YourComponent extends Component {
    
      componentWillMount() {
        /*this fetch function is actually what you want to test*/
        this.props.fetch('data')
      }
    
      render() {
        /* whatever your component renders*/ 
      }    
    }
    

    测试:

    test('should call fetch when mounted', () => {
      let mockFetch = jest.fn()
    
      const wrapper = mount(<SomeComponent fetch={mockFetch}/>);
    
      expect(wrapper).toBeDefined();
      expect(mockFetch).toHaveBeenCalled();
      expect(mockFetch.mock.calls[0]).toEqual(['data'])
    });
    

    【讨论】:

    • 您能否详细说明,如果在 componentWillMount 内部调用的函数实际上是类本身的一部分,例如:this.fetch('data');
    • this.prop.fetch('data') 只是一个例子。为此,我只是调用了一个通过 props 传递给YourComponent 的函数。所以不,不是课程本身的一部分。你真的可以测试任何东西,但这里的基本点是你真的不需要测试componentWillMount 或任何反应生命周期方法。 React/Facebook 会为你做到这一点。只需测试您在这些生命周期方法中编写的代码是否有效。
    • 是的,我明白了。对不起,我不够清楚。如果它们是通过道具传递的函数,我了解如何测试生命周期函数中的所有内容。但是属于组件的函数呢?您将如何测试该函数是否被调用等?如果this.props.fetch() 改为this.fetch(),您将如何测试componentWillMount 内部的函数this.fetch() 被多次调用?
    • 最简单的方法是为此使用 BDD,围绕该方法应该进行的更改进行断言。如果它应该改变 UI 的某些部分,您可以使用酶的 mount 函数,期望某个 DOM 元素/组件存在/不存在。否则,我会使用浅包装组件并使用wrapper.instance().yourMethod(your_arguments) 来测试该方法是否正常运行。我确实希望其他人可以在这里加入,因为这是我能想到的最佳方式。
    • 这是否意味着您在这些生命周期方法中所做的一切都需要成为函数调用?例如,如果我有一个汽车类并且在componentDidMount 我想启动汽车并换档,这两个动作都应该是函数调用(startCarshiftGear),而不是在@987654337 中编写逻辑@?这是一个公平的理解吗?我看到当你使用 Redux 时,这可以通过使用 mapStateToPropsmapDispatchToPropsconnect 中间件来实现。
    【解决方案2】:

    试试这个:

    test('calls `componentWillMount` before rendering', () => {
      const onWillMount = jest.fn();
      SomeComponent.prototype.componentWillMount = onWillMount;
      mount(<SomeComponent />);
    
      expect(onWillMount).toBeCalled();
    });
    

    【讨论】:

      【解决方案3】:

      我首先会在组件的componentWillMount 方法上使用spy,但也会使用.and.CallThrough() 来防止它模拟其内容。希望这会有所帮助:

      it('should check that the componentWillMount method is getting called', () => {
          spyOn(SomeComponent.prototype, 'componentWillMount').and.callThrough();
      
          const wrapper = mount(<SomeComponent />);
      
          expect(wrapper).toBeDefined();
          expect(SomeComponent.prototype.componentWillMount).toHaveBeenCalledTimes(1);
      });
      

      【讨论】:

        【解决方案4】:

        我认为上述答案不能解决问题。这是一个笑话,允许您监视一个方法,但不允许您在监视其调用状态时 callThrough。最适合我的解决方案是使用定义了componentWillMount 的组件来设置测试。开玩笑只会让事情变得更复杂。

        describe('componentWillMount', () => {
          const calls = []
          class Component1 extends Components {
            componentWillMount() {
              calls.push(new Date)
            }
            render() { ... }
          }
          
          afterEach(() => calls.splice(0, calls.length))
          it('has been called', () => {
            mount(<Component1 />)
            expect(calls.length).toBe(1)
          })
        })

        【讨论】:

          【解决方案5】:

          使用wrapper.instance().componentWillMount(); 从测试脚本中调用componentWillMount() 方法..

          【讨论】:

            猜你喜欢
            • 2020-11-12
            • 2021-10-10
            • 1970-01-01
            • 2018-09-28
            • 2019-11-15
            • 2020-07-04
            • 2019-04-24
            • 2017-08-31
            • 1970-01-01
            相关资源
            最近更新 更多