l'essentiel est invisible pour les yeux

Saturday, November 11, 2006

[RSpec] Mock API

Mock Object

Mock Objectの作成


my_mock = mock(<name>)
my_mock = mock(<name>, <options>)
person = mock('person', :null_object => true)


Mockは名前を引数に取る。仕様の検証が終わった際に全てのMockが検証される。
option引数をハッシュで与えることでMockの振る舞いを調整できる。現在、:null_objectのみがサポートされている。:null_object => trueを引数に渡すとMockに対する全てのメソッドがMock自身を返すようになる。

Mockに対してスタブメソッドを定義する

person.should_receive(:name) # person.name => nil
person.should_not_receive(:name) # person.name => raise Spec::Mocks::MockExpectationError


Mockに対して引数を固定してスタブメソッドを定義する

person.should_receive(:say).with(:hello)
person.say(:hello) # => nil
person.say # => raise Spec::Mocks::MockExpectationError


初回の呼び出しのみ引数を固定

person.should_receive(:say).once.with(:hello)
person.say(:hello) # => nil
person.say(:hello) # => raise Spec::Mocks::MockExpectationError


引数を渡さないことを明示的に宣言

person.should_receive(:say).with(:no_args)
person.say(:hellow) # => raise Spec::Mocks::MockExpectationError


引数を取りうる(なしもOK)ことを明示的に宣言
これはwith()のデフォルトの定義である。

person.should_receive(:say).with(:any_args)


スタブメソッドの引数の型のみ指定する。

person.should_receive(:say).with(:string)
person.say('hello') # => nil
person.say(false) # => raise Spec::Mocks::MockExpectationError

:string, :numeric, :boolean, :anythingが指定可能。

should_receiveで定義したメソッドが呼び出される回数を定義する。
デフォルトでは、should_receiveで定義するメッセージは一度だけ呼び出し可能である。

person.should_receive(:say)
person.say(:hello) # => nil
person.say(:hello) # => raise Spec::Mocks::MockExpectationError



person.should_receive(:say).twice
person.say(:hello) # => nil
person.say(:hello) # => nil


メソッドが呼び出される任意の回数を指定する

person.should_receive(:say).exactly(1)
person.say(:hello) # => nil
person.say(:hello) # => raise Spec::Mocks::MockExpectationError


メソッドが呼び出される最小(下限) or 最大(上限)回数を指定する

person.sayを最低2回呼び出すように定義。
person.should_receive(:say).at_least(2)
person.say(:world)
# => raise Spec::Mocks::MockExpectationError


最低n回呼び出すように指定

person.should_receive(:say).at_least(n).times


呼び出される最大回数(上限)を定義

person.should_receive(:say).at_most(:once)
person.should_receive(:say).at_most(:twice)
person.should_receive(:say).at_most(n).times


何度でも呼び出し可能にする

person.should_receive(:say).any_number_of_times


返り値を明示的に定義する

person.should_receive(:say).and_return('Hi!')
person.say # => "Hi!"



person.should_receive(:say).and_return(['Hello', 'world'])
person.say # => ["Hello", "world"]


and_returnにはブロックを渡すことが出来る。ブロックの実行結果が返される。

calc.should_receive(:add).with(:numeric, :numeric).and_return {|a,b| a+b}
calc.add(1,2) # => 3


メソッド呼び出し時に例外を発生させる

person.should_receive(:say).and_raise('error')
person.should_receive(:say).and_throw('error')
person.say # => "error":String


ブロック引数を定義する。メソッド呼び出し時にはブロックを渡す。

person.should_receive(:say).and_yield(1,2)
person.say {|a,b| a+b} # => 3


メソッドが呼び出される順番を明示的に定義する。
should_receiveをordered付きで定義した順番に呼び出しているので検証は成功する。

person.should_receive(:one).ordered
person.should_receive(:two).ordered
person.should_receive(:three).ordered
person.one
person.two
person.three


次の例は、定義した順番で呼び出していないので失敗する。

person.should_receive(:one).ordered
person.should_receive(:three).ordered
person.should_receive(:two).ordered
person.one
person.two
person.three


should_recieveにはブロックを渡すことも出来る。呼び出された際にブロックが実行され検証される。

person.should_receive(:say) do |a,b|
a.should_eql 'hello'
b.should_eql 'world'
end
person.say('hello', 'world')


次の例は第一引数が'hellow'出ないため検証に失敗する。

person.should_receive(:say) do |a,b|
a.should_eql 'hello'
b.should_eql 'world'
end
person.say('hello', 'world')


参考
Mock API