web-dev-qa-db-ja.com

Jestでモックされたサービスにより、「jest.mock()のモジュールファクトリはスコープ外の変数を参照できません」エラーが発生する

サービスの呼び出しをモックしようとしていますが、次のメッセージで苦労しています:jest.mock()のモジュールファクトリは、スコープ外の変数を参照することはできません =。

ES6シンタックス、jest、酵素でbabelを使用しています。

VocabularyからVocabularyEntry- Objectsのリストを取得してレンダリングするvocabularyServiceという単純なコンポーネントがあります。

_import React from 'react';
import vocabularyService from '../services/vocabularyService';

export default class Vocabulary extends React.Component {

render() {

    let rows = vocabularyService.vocabulary.map((v, i) => <tr key={i}>
            <td>{v.src}</td>
            <td>{v.target}</td>
        </tr>
    );
    // render rows
 }
 }
_

vocabularyServiseは非常に単純です:

_  import {VocabularyEntry} from '../model/VocabularyEntry';

  class VocabularyService {

  constructor() {
       this.vocabulary = [new VocabularyEntry("a", "b")];
  }
} 
export default new VocabularyService();`
_

次に、テストでvocabularyServiceをモックしたい:

_import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'

jest.mock('../../../src/services/vocabularyService', () => ({

vocabulary: [new VocabularyEntry("a", "a1")]

}));

describe("Vocabulary tests", () => {

test("renders the vocabulary", () => {

    let $component = shallow(<Vocabulary/>);

    // expect something

});
_

});

テストを実行するとエラーが発生します:Vocabulary.spec.js:babel-plugin-jest-hoist:jest.mock()のモジュールファクトリは、スコープ外の変数を参照できません。無効な変数アクセス:VocabularyEntry。

私が理解していない限り、VocabularyEntryは宣言されていないため使用できません(jestはモック定義をファイルの先頭に移動するため)。

誰も私がこれを修正する方法を説明できますか?モックコール内の参照を必要とするソリューションを見ましたが、クラスファイルでこれを行う方法を理解していません。

18
Ria

問題は、すべてのjest.mockは、コンパイル時に実際のコードブロックの最上部に引き上げられます。この場合は、ファイルの最上部です。この時点では、VocabularyEntryはインポートされません。 mockをテストのbeforeAllブロックに入れるか、jest.mock このような:

import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'
import vocabularyService from '../../../src/services/vocabularyService'

jest.mock('../../../src/services/vocabularyService', () => jest.fn())

vocabularyService.mockImplementation(() => ({
  vocabulary: [new VocabularyEntry("a", "a1")]
}))

これは最初に単純なスパイでモジュールをモックし、すべてのものがインポートされた後、モックの実際の実装を設定します。

12

新しいJest [私の場合は19から21]にアップグレードするときに同様のエラーが発生する場合は、jest.mockからjest.doMock

ここにあります– https://github.com/facebook/jest/commit/6a8c7fb874790ded06f4790fdb33d8416a7284c8

17
Misha Reyzlin

これは私があなたのコードのためにそれを解決する方法です。

モックされたコンポーネントを、「mock」というプレフィックスが付いた変数に保存する必要があります。この解決策は、私が得ていたエラーメッセージの最後にある注に基づいています。

注:これは、初期化されていないモック変数から保護するための予防措置です。モックが遅延して必要であることが保証されている場合、mockで始まる変数名が許可されます。

import {shallow} from 'enzyme';
import React from 'react';
import Vocabulary from "../../../src/components/Vocabulary ";
import {VocabularyEntry} from '../../../src/model/VocabularyEntry'

const mockVocabulary = () => new VocabularyEntry("a", "a1");

jest.mock('../../../src/services/vocabularyService', () => ({
    default: mockVocabulary
}));

describe("Vocabulary tests", () => {

test("renders the vocabulary", () => {

    let $component = shallow(<Vocabulary/>);

    // expect something

});
6
maxletou