Jestを使ってcomponentDidMountのメソッド呼び出しを監視する

最近、ReactコンポーネントのcomponentDidMountメソッドで、あるカスタムメソッドが条件付きで呼ばれることをテストしたいと思いました。

componentDidMount() {
  if (this.props.initOpen) {
    this.methodName();
  }
}

私はテストフレームワークとしてJestを使用しており、モック/スパイのための jest.fn()が含まれています。 以下のようにすれば、Sinonでもかなり簡単にテストできると読みました。

sinon.spy(Component.prototype, "methodName");
const wrapper = mount(<Component {...props} />);
expect(wrapper.instance().methodName).toHaveBeenCalled();

これをJestで以下のように再現しようとしています。

Component.prototype.methodName = jest.fn();
const wrapper = mount(<Component {...props} />);
expect(wrapper.instance().methodName).toHaveBeenCalled();

このコードは失敗し、以下のようなエラーが発生します。

jest.fn() value must be a mock function or spy.
Received:
  function: [Function bound mockConstructor]

この機能をJestでテストすることは可能でしょうか?もし可能ならば、どのようにして?

ソリューション

鍵となるのはjestsのspyOnメソッドを使うことです。以下のようになるはずです。

const spy = jest.spyOn(Component.prototype, 'methodName');
const wrapper = mount();
wrapper.instance().methodName();
expect(spy).toHaveBeenCalled();

ここにあるように 例:https://stackoverflow.com/questions/40393486/test-if-function-is-called-react-and-enzyme

注意 テストを実行するたびに、スパイされた関数をクリアすることも最善の方法です

let spy

afterEach(() => {
  spy.mockClear()
})

https://facebook.github.io/jest/docs/en/jest-object.html#jestclearallmocks

解説 (12)

遅くなりましたが、これを見て、componentDidMountがネストされたメソッドへの呼び出しを開始することをテストするためには、次のようなテストを行うことを提案します。

Module (モジュール)

componentDidMount() {
  if (this.props.initOpen) {
    this.methodName();
  }
}

テスト - 良好

it('should call methodName during componentDidMount', () => {
    const methodNameFake = jest.spyOn(MyComponent.prototype, 'methodName');
    const wrapper = mount();
    expect(methodNameFake).toHaveBeenCalledTimes(1);
});

componentDidMountを呼び出した場合、methodNamecomponentDidMount`を介して呼び出されたというアサーションがより有効になります。

テスト - 悪い

it('should call methodName during componentDidMount', () => {
    const spy = jest.spyOn(Component.prototype, 'methodName');
    const wrapper = mount();
    wrapper.instance().methodName();
    expect(spy).toHaveBeenCalled();
}

このようにテストを書くことで、メソッドを呼び出し、それが呼び出されたことをアサートします。もちろん、メソッドを呼び出しただけなので、呼び出されたことになります。

解説 (3)