LoginSignup
2
3

More than 5 years have passed since last update.

Mocha+Sinon.JSでjQueryのget, ajaxをスタブに置き換えてテストする。

Last updated at Posted at 2017-06-25

概要

jQueryのajaxを使ったコードのユニットテストするために、
今回はSinon.JSのスタブを使って、リモートのAPIを叩かずにテストします。

本記事では、直接jQueryの$.get, $.ajaxを叩いて、
そのcallback内でassertしてますが、
実際のプロジェクトなど、
テスト対象の関数内で$.get, $.ajaxを使ってる場合にも応用できると思います。

Sinon.JSのFake XHRやFake serverを使う方法がネット上にたくさんありますが、
どうもうまくいかなかったのでsinon.stubを利用しました。

20170626 update
その後うまくいく方法が見つかったので別途、投稿しました。
Mocha+Sinon.JSでjQueryのajaxコールを、XMLHttpRequestを置き換えてテストする。 - Qiita

環境

macOS Sierra 10.12.5
Docker for Mac 17.03.1-ce-mac12 (17661)

準備

ローカルの環境を汚さずに済むように、Docker上で環境構築します。

こちらにDockerfileからテストコードまで入ったプロジェクトを上げておきましたので、git cloneして使ってみてください。

環境構築

git cloneしてdocker buildします

$ git clone https://github.com/teruchi/mocha-sinon.git
$ cd mocha-sinon
$ ./docker.sh build

テスト実行!

docker.shの中にdockerコンテナ内でmochaを起動するスクリプトを入れておいたので、それを使います。

$ ./docker.sh mocha

どうでしょう?
こんな感じのメッセージが出力されれば成功です。

  Test User API
    ✓ get /api/users/100
    ✓ ajax /api/users/100


  2 passing (24ms)

解説

Dockerコンテナ内の環境について

Dockerfile

まずDockerfileの説明をします。

Dockerfile
FROM centos:7 【1】

# Install CentOS GPG Key
RUN rpm --import http://vault.centos.org/RPM-GPG-KEY-CentOS-7

# Install EPEL
RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7 && \
    yum install -y epel-release && \
    yum update -y && \
    yum clean all

RUN yum install -y --enablerepo=epel \ 【2】
    nodejs npm && \
    yum clean all

# Javascript Test Suite
RUN npm -g install mocha chai sinon jsdom jquery 【3】
ENV NODE_PATH /usr/lib/node_modules 【4】

# Runtime Setting
WORKDIR /opt 【5】

CentOS 7上に構築しています。 【1】
yumnodejsnpmをインストールした上で、 【2】
npmmochachaisinonjsdomjqueryをインストールしています。 【3】

jsdomを入れないと、ブラウザレスでjQueryを使うことができないので必要でした。

NODE_PATHを指定することで、npm -gでインストールしたパッケージも読みに行くことができるようです。 【4】

docker runした時にテストコードなどが入っているディレクトリでmochaコマンドがすぐ使えるようにWORKDIRをしてしてます。

docker.sh

docker builddocker runでmochaを実行するbashスクリプトの説明をします。

docker.sh
#
# Dockerfile
#
REPO="teruchi/mocha-sinon" 【1】
TAG="latest"
DOCKERFILE="Dockerfile"
SERVICE_NAME="mocha-sinon"


case "$1" in
"build" ) 【2】
    docker build \
      -t ${REPO}:${TAG} \
      -f ${DOCKERFILE} \
      .
    exit
    ;;

"mocha" ) 【3】
    docker run \
      --rm \
      --name ${SERVICE_NAME} \
      -v "$(pwd)"/opt:/opt \
      ${REPO}:${TAG} \
      mocha
    exit
    ;;

*)
    echo "usage: docker.sh [build|mocha]"
    ;;
esac

私の方で利用しているDocker repositoryのパスです。【1】
ご利用の環境に合わせて変更してください。

docker buildしてます。【2】

dockerのvolume mountを使って、ホストのoptディレクトリを、
コンテナ内の/optにマウントすることで、
テストコードを修正しつつ、scpなど使わずにコンテナ内でテストを即実行します。【3】

テストコード

最後になってしまいましたが、テストコードです。

test.js
// Sinon.JS初期化
var sinon = require('sinon');
var assert = require('assert');

// jQuery初期化
var jsdom = require('jsdom/lib/old-api.js');
var window = jsdom.jsdom().defaultView;
var $ = require('jquery')(window);

/**
 * User APIのテスト
 */
describe('Test User API', function () {

    /**
     * $.getのテスト
     * ※callbackの完了を待つ
     */
    it("get /api/users/100", function (done) {
        // sinon.stab で$.getを置き換え
        sinon.stub($, 'get').callsFake(function(url, success, dataType) {
            success({
                id: 100,
                name: 'teruchi'
            });
        });

        // テスト
        $.get(
            '/api/users/100',
            function (data) {
                // Assertion
                assert.equal(100, data.id);
                assert.equal('teruchi', data.name);

                // スタブから元に戻す
                $.get.restore();

                // callback完了をmochaに通知
                done();
            },
            'json'
        );
    });

    /**
     * $.ajaxのテスト
     * ※callbackの完了を待つ
     */
    it("ajax /api/users/100", function (done) {
        // sinon.stab で$.ajaxのreturnのdoneを置き換え
        sinon.stub($, 'ajax').returns({
            done : function(callback) {
                callback({
                    id: 100,
                    name: 'teruchi'
                });
            }
        });

        // テスト
        $.ajax({
            method: 'GET',
            url: '/api/users/100',
            dataType: 'json'
        })
        .done(function(data) {
            // Assertion
            assert.equal(100, data.id);
            assert.equal('teruchi', data.name);

            // スタブから元に戻す
            $.ajax.restore();

            // callback完了をmochaに通知
            done();
        });
    });
});

コメントに書いてある通りですが、ポイントとしては、

  • jsdomを使うことでPhantom.jsなどを使わずにjQueryのテストをする
  • itのパラメーター(done)付きを使うことでcallbackを待つ
  • sinon.stab()でjQueryのメソッドを置き換える

のあたりかと思います。

2
3
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
2
3