Jestを使ってfetch()をモックしたかったです。
いくつかのハマりポイントでハマってしまったのですが解決できました。
Jestの初期化
Jest本体とBabel、今回テストを行いたいnode-fechのモジュールを入れます。
リポジトリを初期化しておきます。
$ yarn init
BabelはJestのテストファイルでimport文などのES6記法を使うために入れています。
$ yarn add --dev jest babel-core babel-jest babel-plugin-transform-es2015-modules-commonjs node-fetch
{
"env": {
"test": {
"plugins": [
"transform-es2015-modules-commonjs"
]
}
}
}
テストファイルを置く
テストコードを先に書いてしまいます。
import fetch from 'node-fetch'
jest.mock('node-fetch', () => jest.fn())
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
const dummyResponse = Promise.resolve({
ok: true,
status: 200,
json: () => {
return {};
},
});
fetch.mockImplementation(() => dummyResponse)
await dummyResponse;
console.log(dummyResponse);
});
});
動かしてみます。
テスト対象コード
'use strict'
var fetch = require('node-fetch');
const makeRequest = async () => {
const res = await fetch("http://httpbin.org/get");
const resJson = await res.json();
return resJson;
};
module.exports = makeRequest;
import fetch from 'node-fetch'
jest.mock('node-fetch', () => jest.fn())
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
const dummyResponse = Promise.resolve({
ok: true,
status: 200,
json: () => {
return {};
},
});
fetch.mockImplementation(() => dummyResponse)
await dummyResponse;
var makeRequest = require('./index'); // テストしたいモジュールを読み込む
makeRequest().then(function (data) { // success
console.log('got data', data); // ダミーレスポンスが帰ってきている
}).catch((e) => { // error
console.log(e.message)
});
});
});
jest.mock('node-fetch', () => jest.fn())
をすることで、本体コード側でnode-fetch
をjest
のモックモジュールに置き換える宣言をしています。
fetch.mockImplementation(() => dummyResponse)
で実際にどんなレスポンスを返すかの実装を行っています。
うまく動きました!
ハマったポイント
proxyquire
JavaScriptのモック用ライブラリにproxyquireがあります。
テストするときには非常に協力なモックライブラリで、具体的にはrequire
を良い感じに乗っ取ってモックされた関数などを返します。
proxyquireでDI もっとモックテストしよう
ただJestとの相性がよくないらしく、Jestではproxyquireが動かない、という報告がありました。
Does not work with proxyquire
実際に今回は動きませんでした。このIssueではjest.mock
を使え、となっていますね。
proxyquire自体も古い1ようで、Jestではjest.mock
を使っていくほうが良いようです。
nock
fetchのモックするためのライブラリにnock
があります。こちらも良く出来たライブラリなのですが、うまく動きませんでした。
【Node.js】nockでtest!
jest-fetch-mock
Jest用のfetchをモックする専用のライブラリ jest-fetch-mock があります。
jest.mock()
汎用のモックシステムなのですが、fetchレスポンスにフォーカスしたライブラリのようです。
こちらもうまく動かせませんでした。
謝辞
今回の件でうまく動かせず色々ヘルプをもらいました。
@say3no @ketch123 @ur0n @naname
ありがとうございました!
StackOverFlowで回答してくれたAndreas Köberleありがとう!
How can I mock fetch function in Node.js by Jest?
-
2018年現在では2015年ぐらいの記事が多かったです。 ↩