首页 > 解决方案 > 如何监视在 componentDidMount 内部调用的方法

问题描述

我试图监视一个在 componentDidMount 内部调用的方法。该方法本身位于另一个文件中。这是我到目前为止所尝试的:

import apicall from './AnotherFile'
class MyComponent {
    componentDidMount() {
        apicall()
    }
    <other code ->
}

测试:

const wrapper = mount(<MyComponent/>);
const instance = wrapper.instance();
jest.spyOn(instance, 'apicall');
instance.componentDidMount();
expect(instance.apicall).toHaveBeenCalled();

它给出了一个错误:

Cannot spy the apicall property because it is not a function; undefined given instead

知道如何实现吗?

标签: reactjsjestjs

解决方案


有几种方法可以做到这一点:

  1. 在您的测试文件中模拟导入:通过 using jest.mock,Jest 将拦截导入并在组件文件中使用它时创建一个模拟版本:

    // MyComponent.test.js
    import apicall from './AnotherFile'
    
    jest.mock('./AnotherFile');
    
    it('makes API call', () => {
      const wrapper = mount(<MyComponent />);
      expect(apicall).toHaveBeenCalled();
    });
    

无需获取instance,无需手动调用componentDidMount,当你会发生的mount(<MyComponent />)。注意:如果apicall应该返回一个值或一个承诺,你可以提供一个模拟值:

// Mock a response if your componentDidMount calls `apicall.then()`...
apicall.mockImplementation(() => Promise.resolve('some value'));
// Mock a rejected Promise to test error cases
apicall.mockImplementation(() => Promise.reject('Oh no!'));
  1. 依赖注入:将函数传递apicall到您的组件中。您可以将其默认为apicall您导入的实际值,但在测试中您可以传入一个模拟函数:

    // MyComponent.js
    import apicall as realApiCall from './AnotherFile'
    
    class MyComponent extends Component {
    
      static defaultProps = {
        apicall: realApiCall
      }
    
      componentDidMount() {
        // This will call the real apicall if you don't provide
        // a prop: <MyComponent /> ... but allows you to inject
        // a mock apicall function in tests.
        this.props.apicall()
      }
      <other code ->
    }
    
    // MyComponent.test.js
    const apicall = jest.fn();
    const wrapper = mount(<MyComponent apicall={apicall} />);
    expect(apicall).toHaveBeenCalled();
    

推荐阅读