😎
Node.jsのfetchをmockしたい
概要
Node.jsのfetchをmockする場合、 fetch-mockを利用するのが一般的なようです。
簡単な処理をmockしたかっただけなので、わざわざモジュールを使うまででもないと思い、自分でmockする処理を作成しました。
試したNode.jsのバージョンは v18.17.1
です。
fetchについて
Node.jsではv18.0.0からfetchが利用できるようになっています。
A browser-compatible implementation of the fetch() function.
と書いてある通り、基本的にブラウザのfetchと同じ動きをするようです。
globalで定義されているので、これを置き換えられれば大丈夫そうです。
ブラウザ側のfetchについて
fetchはPromise<Response>
を返すので、それを実装しておけばよさそうです。
実装
今回はjsonの結果のみ欲しかったので、他は極力空の値を返すようにしています。
global.fetch = () => new Promise((resolve) => resolve(({
ok: true,
headers: {
append: () => { },
delete: () => { },
get: () => null,
has: () => false,
set: () => { },
forEach: () => { },
// node18だと以下のメソッドがあるとエラーになる。
// mdnのドキュメントにはある
// getSetCookie: () => [],
// entries: function (): IterableIterator<[string, string]> {
// throw new Error('Function not implemented.');
// },
// keys: function (): IterableIterator<string> {
// throw new Error('Function not implemented.');
// },
// values: function (): IterableIterator<string> {
// throw new Error('Function not implemented.');
// },
// [Symbol.iterator]: function (): IterableIterator<[string, string]> {
// throw new Error('Function not implemented.');
// }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
redirected: false,
status: 200,
statusText: 'OK',
type: 'basic',
url: '',
// mockしたいのはこの部分
json: () => new Promise((r) => r({
hoge: "hoge",
foo: "bar",
})),
body: null,
bodyUsed: false,
arrayBuffer: () => new Promise((r) => r(new ArrayBuffer(0))),
blob: () => new Promise((r) => r(new Blob())),
formData: () => new Promise((r) => r(new FormData())),
text: () => new Promise((r) => r('')),
clone: function () { return this },
})));
headersは本来であれば、Headersのinterfaceを満たすものになります。
しかしながら、as any
を設定しないと実行時に以下のようなエラーが発生します。
Object literal may only specify known properties, and 'getSetCookie' does not exist in type 'Headers'.
結論
fetchの関数をライブラリを利用せずに手軽にmockが書けました。
原因はわかっていませんが、ブラウザ側にしたがってそのまま記述すると型のエラーになるので、 as any
で回避する必要がありました。
Discussion