の使い方を覚えた。 with にブロックをあたえると expects に指定したメソッドと同じ引数を受け取り、ブロックが評価される。ブロックが真を返すかどうかが影響するので、ブロックの中に assert を書いたりしないように注意。以下のてきとうな例では、 LWP::Simple.getprint メソッドの中で実行されるメソッド呼び出しが期待したとおりに動いているか、を、テストしているつもり。
https://gist.github.com/1099986
require 'net/http' module LWP class Simple def self.getprint(url) uri = URI(url) Net::HTTP.start(uri.host, uri.port){ |http| http.get(uri.path).body } end end end if $0 == __FILE__ eval DATA.read end __END__ require 'test/unit' require 'mocha' class TestLWPSimple < Test::Unit::TestCase def test_valid_path Net::HTTP.any_instance.expects(:get).with{ |path| path == '/a666666/about' }.returns(stub('response', :body)) LWP::Simple.getprint("http://d.hatena.ne.jp/a666666/about") end end
ちょっと脱線して、スタブとモックについて最近意識していること。というか以前に比べてそれらをどう使い分けるのか?についての自分なりの考え方が固まってきたので書いてみる。
スタブは単に「ここから先は無視してオッケー」という部分を無効化するくらいの気持ちで使ってる。上のコードを例にとると、 http.get() は HTTPResponse クラスのインスタンスを返すべきであり body というインスタンスメソッドを呼び出せるべきである、が今はそんなことはどうでもいいので、単に body メソッドの呼び出しでエラーにならないようにスタブしている。
モックは込み入っていて、あるメソッド foo が何らかのデータを加工して他のメソッド bar を呼び出すとき、「foo を呼び出したならば bar も呼び出されるべきである」ということをテストしたいし、むしろ「foo を呼び出したならば bar に渡すデータをただしく作成できるべきである(ついでに bar も呼び出されるべきである)」くらいの気持ちでモックを使うことが多い。
どちらも foo メソッドがおこなう処理を手続き的に見ていて、メソッド呼び出しに注目しているときはフロー制御的な側面から「foo メソッドはこういう順序で各種の手続きを実行します」ということをテストしようとしており、データに注目しているときはデータ処理的な側面から「foo メソッドはこういう手続きを経てこのようにデータを加工します」ということをテストしようとしている。という意識でおれはスタブとモックを使い分けていますよ、という話。
ここでさらに先日の RubyKaigi で発表されていた Fake を取り上げてその違いにも注目したいところなんだけどあいにく Fake が何かぼんやりとしかわかってないし実際に試してみたこともないのでそれは皆さんへの宿題にします!今後の楽しみにとっておきます...