web-dev-qa-db-ja.com

Jestjs別の関数内で呼び出される関数をテストする方法

テストには、jestとreact-test-rendererを使用します。テストは簡単なはずですが、適切な例を見つけるのに苦労しています。私はそのようなことをしようとしました(一般的に私は関数を別々のファイルに保持します):

utils.js

export const childFunction = () => 'something';    
const parentFunction = () => childFunction();
export default parentFunction;

utils.test.js

import parentFunction from './utils.js';


it('childFunction should be called', () => {
 const childFunction = jest.fn();
 parentFunction();
 expect(childFunction).toBeCalled();
})

フラグメントconst childFunction = jest.fn();は間違いなく機能しません。呼び出し中、parentFunctionの本体は自身のスコープのみを考慮します。ただし、childFunctionをインポートしてjest.mock(childFunction)を実行しても機能しません。jest.mockには、関数自体ではなく、文字列、モジュールのURLが必要だからです。

上記の例は機能せず、別の方法を探しています。ただし、これはShallowRendererでコンポーネントをレンダリングした後に機能します。そして、別の関数内にネストされた関数で同様の動作を実現したいと思います。

class Component extends React.Component {
 componentDidMount() {parentFunction()}
 render() {...}
}

const renderer = new ShallowRenderer();
describe("testing parentFunction", () => {
  renderer.render(<Component/>);
  it("parentFunction should be called", () => {
    expect(parentFunction).toBeCalled();
  });
});
6
Dune

関数がオブジェクトメソッドとして呼び出されない場合、関数呼び出しをスパイする方法はありません。

この回答 で説明されているように、ESモジュールの動作方法により、モジュールからエクスポートされて別のモジュールで使用されている場合にのみ、関数をスパイまたはモックすることができます。このようにして、モジュール*オブジェクト、またはjest.mock

そうでない場合は、間接的にテストする必要があります。

expect(childFunction()).toBe('something');
expect(parentFunction()).toBe('something');
3
Estus Flask

これが役立つかどうかはわかりませんが、アイデアを提供してくれるかもしれません。

まず、上記の例:

// this needs to be stubbed
// const childFunction = () => 'something';
const childFunction = jest.fn();

const parentFunction = () => childFunction();

it('childFunction should be called', () => {
    parentFunction();
    expect(childFunction).toHaveBeenCalled();
}

childFunctionがエクスポートされる可能性は低いため、これへの参照を取得してモック/スタブできないため、これはやや不自然な例です。

あなたが持っている1つの回避策は、それを独自のメソッドに移動することです

class Component extends React.Component {
  componentDidMount() {
    this.parentFunction();
  }
  parentFunction() {
    parentFunction(); // from elsewhere
  }
  render() {...}
}

これにより、コンポーネントプロトをパンクしてスパイを作成できます。

例えば

const spy = jest.spyOn(Component.prototype, 'parentFunction');

// ... mount so lifecycle runs... 
expect(spy).toHaveBeenCalled(); // and clear the spy mocks after!

モジュールをモックする方が良いかもしれません

たとえば、コンポーネントで使用されるutils.jsがあります。

export function parentFunction(){ console.log('parent'); }

component.jsの機能:

import { parentFunction } from './utils';

あなたのテストでできます:

const utils = require('./utils');
utils.parentFunction = jest.fn();
import Component from './component';
// later
expect(utils.parentFunction).toHaveBeenCalled();

ご覧のとおり、多くの可能な方法がありますが、そのテストの値はわかりませんが、おそらくcomponentDidMountで何かを実行して、呼び出されたのではなく、コンポーネントの出力/機能をテストする必要がありますは与えられており、誰かが機能に変換したか、ライフサイクル名を変更した場合にのみ壊れます。

2