node.jsのソースを単体テストする際のmocha+sinonの使い方

node.jsのソースをmochaでテストしているとsinonでモックしてテストする、といったケースがあると思います。

node.jsのソースを単体テストする際のmocha+sinonの使い方

sinonは英語ドキュメントもありますし、広く使われているモジュールなのでモックの方法がネットにごろごろ転がっています。

簡単なソースでsinonを試してみたいと思います。

以下をindex.jsで保存します。

function testMethod(money=0){
  money = money * 1.08;
  return money;
};
exports.sample = testMethod;

exports.sampleという変数にtestMethodを代入します。これでtestMethodをsampleという名前で他のモジュールからも使えるようにします。

このtestMethodの戻り値をsinonでモックしてみます。

以下、index.test.jsです。

const chai = require('chai');
const sinon = require('sinon');
const assert = chai.assert;
const expect = chai.expect;
const target = require('../../main/sample001/index.js');// requireする

describe('sinon', function () {
  it('sinonのテスト', function(){
    let stub = sinon.stub(target,'sample');// targetのsampleをスタブする
    let expected = 110;
    stub.returns(expected);// sampleの戻り値は110にしてみる
    let ret = target.sample(50);
    console.log(ret);
    expect(expected).to.equal(ret);
  });
});

stub.returnsで戻り値を指定しているので、これでモックができたことになります。

そのあとにsample()を実行すると引数が何であっても戻り値は指定した戻り値となります。

結果は以下のようになります。

node.jsのソースを単体テストする際のmocha+sinonの使い方

メソッド内のメソッドをsinonでモックする

実際はメソッド内にあるDBに検索するメソッドなどをモックするというケースが多いかと思います。

以下はメソッド内のメソッドをモックする例です。

function testMethod(money=0){
  let self = this;
  money = money * self.getTax();// 消費税を別のメソッドから取得
  return money;
};

function getTax() {
  return 1.08;// DBから取得しているイメージで、、
}
module.exports = {
  sample: testMethod,
  getTax: getTax
};

getTaxは通常はDBから取得すると思いますが、モックできるかのテストなので1.08を返すだけにしました。

index.test.jsで1.08を返すのをスタブ化し、1.10を返すようにしています。テスト自体はtestMethodメソッドから実行しています。

const chai = require('chai');
const sinon = require('sinon');
const assert = chai.assert;
const expect = chai.expect;
const target = require('../../main/sample001/index.js');

describe('sinon', function () {
  it('sinonのテスト', function(){
    let stub = sinon.stub(target,'getTax');// スタブする
    let val = 1.10;
    stub.returns(val);// getTaxメソッドの戻り値は1.10
    let ret = target.sample(100);// インプットは100
    let expected = 110;// 期待値は110
    expect(expected).to.equal(parseInt(ret));
  });
});

オブジェクトのキーに対するプロパティをモックする
sinon.sandbox.create()メソッドでsandboxオブジェクトを返します。

sandbox.stub(オブジェクト,'キー').values('モックしたい値')

このように記述するとオブジェクトのキーに対するプロパティをモックすることができます。

以下、実行例です。

const chai = require('chai');
const sinon = require('sinon');
const assert = chai.assert;
const expect = chai.expect;

describe('sinon', function () {
  let sandbox;
  beforeEach(function () {
    sandbox = sinon.sandbox.create();
  });
  it('sinonのテスト', function(){
    const myObject = {
      'hello': 'world'
    };
    sandbox.stub(myObject, 'hello').value('Sinon');
    let expected = 'Sinon';
    expect(expected).to.equal(myObject.hello);
  });
  afterEach(function () {
    sandbox.restore();// リストアすること
  });
});

結果は成功します。

node.jsのソースを単体テストする際のmocha+sinonの使い方

sinonのエラー

Cannot stub non-existent own property XXX

…XXXというメソッドがない場合にこのエラーが発生する。

TypeError: Attempted to wrap execute which is already wrapped

…すでにモックしているものをもう一度モックしようとすると発生する。

sinonの評価はmocha+chaiの使い方を参照して下さい。

process.env(環境変数)をモックする方法

process.env(環境変数)をモックするにはsandboxを使用します。

beforeEachでsandboxを作成し、afterEachでrestoreします。

sandbox.stub(process.env, 'PATH').value('12345');// 環境変数PATHを12345にモック

上記で環境変数PATHの値を変えることができます。但し、環境変数がPCに設定されていない場合は以下のようなエラーとなります。

TypeError: Cannot stub non-existent own property PATH

以下、実行例です。

const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;

describe('sinon', function () {
  let sandbox;
  beforeEach(function () {
    sandbox = sinon.sandbox.create();
  });
  it('sinonのテスト', function(){
    sandbox.stub(process.env, 'PATH').value('12345');
    expect(process.env.PATH).to.equal('12345');// passになる
  });
  afterEach(function () {
    sandbox.restore();
  });
});

参考サイト

スポンサーリンク
  • このエントリーをはてなブックマークに追加
スポンサーリンク

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA