Help us understand the problem. What is going on with this article?

node環境でsinon.jsのfakeServerを使う

More than 3 years have passed since last update.

やりたいこと

node.js環境でsinonのfakeServerを使いたい。

なんで?

sinonのfakeServerを使うと、特定のurlへのアクセスに対して任意のステータスコード、ヘッダー、レスポンスボディを返すstubサーバを作る事ができ、APIを呼んだらこうなる、というテストを書く事ができる。

sinon.js#server

しかし、このfakeServerはnode環境だと使えない。sinon.jsの初期化処理を眺めるとわかるが、global環境にXMLHttpRequestが定義されているか否か、そのXMLHttpRequestオブジェクトにwithCredentials属性があるか否か、といったことをチェックしており、実行環境にXMLHttpRequestがあることが前提となっている。

対処法

てことは、globalにXMLHttpRequestのインタフェースを実装してあげれば良さそうである。自分で一通りインタフェースを実装すれば良いのかもしれないが、その前にGoogle先生に聞いてみると、node-xmlhttprequestなる、XMLHttpRequestをnode.js上で実装したモジュールが出てくる。一通りXMLHttpRequestのインタフェースが実装されているので、テスト環境においてこのモジュールをglobal.XMLHttpRequestに設定してあげると、sinon.jsの初期化時にXMLHttpRequestが検出され、fakeServerがちゃんと動作するようになる。

コード

以下サンプルコード。XMLHttpRequestをglobalに設定するファイル(browser.js)とsinonの読み込みは別ファイルにして、必ずbrowser.jsを先に読み込ませる。一つのファイル内でどうにかできないもんかと思いつつ、ES6のimportやglobalが最終的にどうコンパイルされるかまで見てないのでよくわからず。。。

個人的な事情で、mochachaiのテストコードです。

mocha --compilers js:babel/register test.js
browser.js
// ブラウザ環境っぽいものを作る
import jsdom from 'jsdom';
import jQuery from 'jquery';
import { XMLHttpRequest } from 'w3c-xmlhttprequest';

global.XMLHttpRequest = XMLHttpRequest;
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.parentWindow;
global.$ = jQuery(window);
test.js
// chai使ってます
import './browser';
import chai, { expect } from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
chai.use(sinonChai);

describe('FakeServer in node.js', () => {
  let server;
  let spy;
  beforeEach(() => {
    server = sinon.fakeServer.create();
    spy = sinon.spy();
  });
  afterEach(() => {
    server.restore();
  });
  it('fake responseが返ること', () => {
    server.respondWith('GET', '/sample.json', [
      200,
      { 'Content-Type': 'application/json' },
      JSON.stringify({message: 'Hello World'})
    ]);
    $.getJSON('/sample.json')
     .then((data) => {
       spy(data);
     });
    server.respond();
    expect(spy).to.have.been.calledWith({message: 'Hello World'})
  });
});

まとめ

node環境でもfakeServer使えそうです。

同じようなXMLHttpRequest in node.js実装として、xhr2というのもあったのだけど、こっちではうまく動きませんでした。withCredentialsが実装されてないのが原因っぽいですが、詳細は追ってません。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした