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