Reactjs 如何监视在componentDidMount内部调用的方法

Reactjs 如何监视在componentDidMount内部调用的方法,reactjs,jestjs,Reactjs,Jestjs,我试图监视一个名为inside componentDidMount的方法。方法本身驻留在另一个文件中。以下是我迄今为止所做的尝试: import apicall from './AnotherFile' class MyComponent { componentDidMount() { apicall() } <other code -> } import apicall from./AnotherFile' 类MyComponent{ co

我试图监视一个名为inside componentDidMount的方法。方法本身驻留在另一个文件中。以下是我迄今为止所做的尝试:

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

const wrapper=mount();
const instance=wrapper.instance();
jest.spyOn(例如,“apicall”);
componentDidMount();
expect(instance.apicall).tohavebeencall();
它给出了一个错误:

无法监视apicall属性,因为它不是函数;而不是给定未定义的


知道如何实现吗?

您模拟了导入的函数。试试这个

    import * as dependency from '../AnotherFile';

    describe('MyComponent', () => {
        it('test apicall', () => {
            dependency.apicall = jest.fn();

            const wrapper = mount(<MyComponent />);
            wrapper.instance().componentDidMount();

            expect(dependency.apicall).toHaveBeenCalled();
        });
    });
import*作为依赖项从“../AnotherFile”导入;
描述('MyComponent',()=>{
它('testapicall',()=>{
dependency.apicall=jest.fn();
const wrapper=mount();
wrapper.instance().componentDidMount();
expect(dependency.apicall).tohavebeencall();
});
});

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

  • 在测试文件中模拟导入:通过使用
    jest.Mock
    ,jest将拦截导入并在组件文件中使用时创建模拟版本:

    // MyComponent.test.js
    import apicall from './AnotherFile'
    
    jest.mock('./AnotherFile');
    
    it('makes API call', () => {
      const wrapper = mount(<MyComponent />);
      expect(apicall).toHaveBeenCalled();
    });
    
  • 依赖项注入:
    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();
    
    //MyComponent.js
    从“./AnotherFile”将apicall作为realApiCall导入
    类MyComponent扩展组件{
    静态defaultProps={
    真的吗
    }
    componentDidMount(){
    //如果您不提供,这将称为真正的apicall
    //道具:……但允许你注射
    //测试中的模拟函数。
    this.props.apicall()
    }
    }
    //MyComponent.test.js
    const apicall=jest.fn();
    const wrapper=mount();
    expect(apicall).tohavebeincall();
    

  • 尝试复制到本地属性:_apicall=apicall,然后在spyOn()中使用“_apicall”,但如果不使用此属性,则该解决方案将不完整。_apicall()在componentDidMount()中。。。可能spyOn会为本地函数准备一个包装器。你能举个例子吗?得到这个错误:预期模拟函数已被调用,但未被调用。请尝试删除括号,如so
    dependency.apicall=jest.fn相同错误:`Matcher error:当我尝试方法1时,收到的值必须是模拟或间谍函数`
    
    // 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!'));
    
    // 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();