Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

fetch-mockでnodeでのfetch入りモジュールをテストする

Posted at

nodejsでfetchが入っているモジュールの単体テスト

nodejs上でfetchを使い、別のサーバーにRESTコールを投げる場合があります。
そのようなコードを単体テストする際に、実際に他のサーバーに処理を投げると他サーバーに引きずられてテストが不安定になるため、モックにしたいところです。
そこで、fetch-mock というライブラリを利用してモックする手順についてまとめました。

fetch-mock

fetch-mockはfetchを独自のモックに置き換え、指定したレスポンスを返すように設定できるライブラリです。

グローバルfetchを使う場合の使い方

fetch-mockのデフォルトの挙動では、グローバルオブジェクトに登録されているfetchを置き換えてくれます。公式サイトにも載っているサンプルを元に説明します。
nodeではネイティブでfetchがglobalオブジェクトには紐付いておらず、この方法は使えません。nodeでは別途後述するsandboxメソッドを使わないとだめですが、挙動はほぼ変わらないので、まずはfetch-mockの本来の使い方について触れます。

make-request.js
module.exports = function makeRequest() {
  return fetch("http://httpbin.org/get").then(function(response) {
    return response.json();
  });
};

httpbin.org/getに対してgetリクエストを出して、そのレスポンスをJSONパースしてオブジェクトとして返します。httpbin.org/getのエンドポイントは実在していて、モックせずにfetchするとちゃんとしたレスポンスが返ってきます。
このソースコードに対するテストとして下記のようなテストを書きます。

test.js
var fetchMock = require('fetch-mock');
var makeRequest = require('./make-request');

// Mock the fetch() global to always return the same value for GET
// requests to all URLs.
fetchMock.get('*', {hello: 'world'});

makeRequest().then(function(data) {
  console.log('got data', data);
});

// Unmock.
fetchMock.restore();

fetchMock.getによりグローバルのfetchオブジェクトをfetchMockが作ったモックに置き換えています。
第一引数は対象のURLを示しており、このサンプルでは*にしているため、全てのURLが対象になります。
第二引数はレスポンスを示していて、{hello:'world'}というJSONをレスポンスとして返します。
この状態でfetchを呼ぶと、どのURLに対してアクセスしても第二引数のレスポンスが返ってきます。
実際に実行すると下記のようになります。

$ node mocked.js
'got data' { hello: 'world' } 

非グローバルなfetchを使うやり方

nodeを使っている場合、前述した通りfetchはグローバルオブジェクトには紐付いておらず、node-fetchなどを持ってくる必要があります。。make-request.jsでいうと、例えば下記のようなコードになります。

make-request-node-fetch.js
var fetch = require('node-fetch')
module.exports = function makeRequest() {
  return fetch("http://httpbin.org/get").then(function(response) {
    return response.json();
  });
};

ここで使うfetchはグローバルなものではないので、fetchMockでmockしても置き換わってくれません。
そこで、sandboxというメソッドを使ってモックを作り出します。作り出したモックは任意のスタブ組み込みライブラリで組み込む必要があります。
ここではproxyquireをスタブ組み込みライブラリとして使用します。

test.js
var fetchMock = require('fetch-mock');
var proxyquire = require('proxyquire')

var myMock = fetchMock.sandbox().mock('*',{hello: 'world'});
var makeRequest = proxyquire('./make-request-node-fetch',{
  'node-fetch': myMock
});

makeRequest().then(function(data) {
  console.log('got data', data);
}).catch((e) => { console.log(e.message)});

proxyquireを使ってmake-request.js内でのrequire('node-fetch')で返ってくるfetchメソッドをモックしています。
proxyquireは今回ちょろっと紹介しただけですが、これも非常に便利なのでテストに多用できると思います。

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?