sinonとCoffeeScriptでクラスのテストをしたい時はprototypeにstubを刺す

sinonとcoffee-scriptでテストするとき、どうやったらいいかな、ということを考えてて、色々やった結果上の結論に自分の中で至った。のでやり方だけ書いておく。

こんなモックがあるとする。

class MockClass
  method: ->
  method2: ->

ここではメソッドを定義するだけ。

sinonでメソッドの振る舞いを決める。

...
sinon = require 'sinon'
sinon.stub(MockClass.prototype, 'method').withArgs(1).returns 42

1を引数にとった時、42を返すメソッドにした。

newされたインスタンスが、そのように振る舞う。

mock = new MockClass
console.log mock.method(1) #=> 42
console.log mock.method(0) #=> undefined

なにも定義されていない場合、undefinedがreturnされる。殆どの場合は返り値でassertionするので問題ない。

sinon.match

数字を引き取った場合、42 * 42 を返すようにする。

sinon.stub(MockClass.prototype, 'method2').withArgs(sinon.match.number).returns 42 * 42
console.log obj.method2(424239748923) #=> 1764

sinon.mock

あるオブジェクトに対して、どのようにメソッドを叩いているかをテストしたいときはsinon.mockを使う。

class MockClass2
  a: (str) -> @b(str); @b(str)
  b: (str) -> str

モック化して振る舞いを決める

mock = sinon.mock(MockClass2.prototype)
mock.expects('b').twice().withArgs('hoge')

「bメソッドを"hoge"という引数で二回叩く」ことを期待する。
実際にaを叩いてbが二回呼ばれたことを確認。

m3 = new MockClass2
m3.a("hoge")
mock.verify() #=> pass test
mock.restore() # もとに戻す

verifyでちゃんとテストが走ったか確認。違った場合は例外を吐く。
できた。