Jestでテストしようとしている次のモジュールがあります。
// myModule.js
export function otherFn() {
console.log('do something');
}
export function testFn() {
otherFn();
// do other things
}
上記に示すように、いくつかの名前付き関数をエクスポートし、重要なことにtestFn
はotherFn
を使用します。
Jestでは、testFn
の単体テストを作成するときに、otherFn
のエラーをotherFn
の単体テストに影響させたくないため、testFn
関数をモックしたいと思います。 ] _。私の問題は、それを行う最善の方法がわからないということです。
// myModule.test.js
jest.unmock('myModule');
import { testFn, otherFn } from 'myModule';
describe('test category', () => {
it('tests something about testFn', () => {
// I want to mock "otherFn" here but can't reassign
// a.k.a. can't do otherFn = jest.fn()
});
});
どんな助け/洞察も大歓迎です。
jest.requireActual()
内でjest.mock()
を使用する
jest.requireActual(moduleName)
モックの代わりに実際のモジュールを返します。モジュールがモック実装を受信するかどうかのすべてのチェックをバイパスします。
返されたオブジェクトを必要とし、そのオブジェクト内で拡散する場合、この簡潔な使用を好む:
// myModule.test.js
jest.mock('./myModule.js', () => (
{
...(jest.requireActual('./myModule.js')),
otherFn: () => {}
}
))
describe(...)
このメソッドは、JestのManual Mocksドキュメントでも参照されています( Examples の終わり近く):
手動モックとその実際の実装の同期を維持するために、手動モックで
jest.requireActual(moduleName)
を使用し、エクスポートする前にモック関数で修正する実際のモジュールを要求することが役立つ場合があります。
import m from '../myModule';
私にはうまくいきません、私は使用しました:
import * as m from '../myModule';
m.otherFn = jest.fn();
トランスコンパイルされたコードは、otherFn()
が参照しているバインディングをbabelが取得することを許可しません。関数式を使用する場合、モックotherFn()
を達成できるはずです。
// myModule.js
exports.otherFn = () => {
console.log('do something');
}
exports.testFn = () => {
exports.otherFn();
// do other things
}
// myModule.test.js
import m from '../myModule';
m.otherFn = jest.fn();
しかし、前のコメントで@kentcdoddsが言及したように、おそらくotherFn()
をモックしたくないでしょう。むしろ、otherFn()
の新しい仕様を記述し、それが行っている必要な呼び出しをモックするだけです。
たとえば、otherFn()
がhttpリクエストを行っている場合...
// myModule.js
exports.otherFn = () => {
http.get('http://some-api.com', (res) => {
// handle stuff
});
};
ここでは、http.get
をモックし、モックされた実装に基づいてアサーションを更新します。
// myModule.test.js
jest.mock('http', () => ({
get: jest.fn(() => {
console.log('test');
}),
}));
私はこのパーティーに遅れているように見えますが、はい、これは可能です。
testFn
は、otherFn
を呼び出すだけで済みますモジュールを使用して。
testFn
がモジュールを使用してotherFn
を呼び出す場合、otherFn
のモジュールエクスポートはモックでき、testFn
はモックを呼び出します。
これが実際の例です:
myModule.js
import * as myModule from './myModule'; // import myModule into itself
export function otherFn() {
return 'original value';
}
export function testFn() {
const result = myModule.otherFn(); // call otherFn using the module
// do other things
return result;
}
myModule.test.js
import * as myModule from './myModule';
describe('test category', () => {
it('tests something about testFn', () => {
const mock = jest.spyOn(myModule, 'otherFn'); // spy on otherFn
mock.mockReturnValue('mocked value'); // mock the return value
expect(myModule.testFn()).toBe('mocked value'); // SUCCESS
mock.mockRestore(); // restore otherFn
});
});
ここでの最初の答えに加えて、 babel-plugin-rewire を使用して、インポートされた名前付き関数もモックできます。 named function rewiring のセクションを表面的に確認できます。
ここでの状況に対する直接的な利点の1つは、関数から他の関数を呼び出す方法を変更する必要がないことです。