2017-07-10

sinonでmockしてみた

やってみた

内容は以下のような感じで、Node.js ネイティブ環境では動かないオブジェクトに対して、それでも期待通りに呼び出されたかどうかを確認するためのテスト。

describe('SpreadsheetApp return ActiveSheet', ()=> {
  it('called getActiveSheet() once', ()=> {
    // まず Node.js 環境で動かないメソッド呼び出しを stub out
    // SpreadsheetApp -> Spreadsheet -> Sheet の構造があって、
    // getActiveSheet() は中間のオブジェクトの持つメソッドで、どうやっても動かせない
    // これを spreadsheet.book().sheet() の構造にマップしようとしている
    // getActiveSheet() メソッドを持つダミーのオブジェクトを返すメソッドを stub out
    sinon.stub(spreadsheet, 'book').returns({getActiveSheet: function() { return {} }})

    // stub out したメソッドを mock にして期待する動作を設定
    let book = sinon.mock(spreadsheet.book())
    book.expects('getActiveSheet').once()

    // メソッドを実行したのち、結果の verify
    spreadsheet.sheet()
    book.verify()
  })
})

※ もちろんこれをコピペしても動きません

ポイント

  • 恐らくイマドキ JavaScript のテストのかなりの割合は Node.js 上で実行されている
  • Node.js 環境には存在しないオブジェクト、メソッドに対して期待する振る舞いを記述するために、まず stub out する(でないと実際に呼び出されてしまったらエラーになる)
  • そのうえで stub out したメソッドが期待通り呼び出されたかどうかを mock で verify する

で、たぶん合ってると思います。間違えてたら教えてくだしあ。

参考

Sinon.JS - Standalone test spies, stubs and mocks for JavaScript. Works with any unit testing framework.

この中の mock の記述、分かったような分からないような感じなんですよね。というか RSpec の時もそうだったんだけど、mock の説明の記述って汎用的に書かれているとほんとによく分からないので、個人的には RR の記述が分かりやすくてよかったのでオススメです。

RR - a test double framework for Ruby

RR は RR の記述そのものがすごくシンプルで分かりやすく、意味の方に集中しやすくてよいです。(が、RSpec 3+ とは完全には統合できないので注意が必要)

About

例によって個人のなんちゃらです