こんな風にモックを使ってテストすればいいのかな.変な点があったら指摘して下さると嬉しいです.
目標
Twitterとは通信せずにTwitterクラスを使うコードのテストを行う(Twitterクラス関連のコードは適当にパスさせる)
sample_tweet.rb
- SampleTweetのコンストラクタでTwitter::Baseクラスのインスタンス@twitterを作る
- SampleTweet#hogeメソッドで@twitter.updateを呼び出し"hoge"という文字列をTwitterにpostする
#!/usr/bin/env ruby require 'rubygems' require 'twitter' class SampleTweet def initialize(consumer_token_key, consumer_secret, access_token_key, access_secret) # OAuthで認証する oauth = Twitter::OAuth.new(consumer_token_key, consumer_secret) oauth.authorize_from_access(access_token_key, access_secret) @twitter = Twitter::Base.new(oauth) end def hoge # Twitterに"hoge"とpostする @twitter.update("hoge") end end
sample_tweet_spec.rb
- SampleTweet#hogeを実行して例外が発生しないことを確認する程度のテストを行う
- Twitterとは通信せずにSampleTweet#hogeのテストを行う(Twitterクラス関連のコードは適当にパスさせる)
- Twitter::OAuthやTwitter::Baseのモック(偽物)を作り,各メソッドを偽装して何も処理しないようにする
- Twitter::OAuthやTwitter::Baseのnewがモックのインスタンスを返すように偽装する
sample_tweet_spec.rb
require 'sample_tweet.rb' describe SampleTweet do before(:all) do # Twitter::OAuthのモックを作り,メソッドを偽装する @oauth = mock(Twitter::OAuth) @oauth.stub!(:authorize_from_access).with( 'dummy_access_token_key', 'dummy_access_secret') # Twitter::OAuth.newがモックのインスタンスを返すようにする Twitter::OAuth.stub!(:new).with( 'dummy_consumer_token_key', 'dummy_consumer_secret' ).and_return(@oauth) # Twitter::Baseのモックを作り,メソッドを偽装する @twitter = mock(Twitter::Base) @twitter.stub!(:update) # Twitter::Base.newがモックのインスタンスを返すようにする Twitter::Base.stub!(:new).with(@oauth).and_return(@twitter) # SampleTweetクラスのインスタンスを作る @sample = SampleTweet.new( 'dummy_consumer_token_key', 'dummy_consumer_secret', 'dummy_access_token_key', 'dummy_access_secret') end # SampleTweet#hogeのテスト(Twitterにはpostされない) it 'should post "hoge" to twitter' do @sample.hoge end end
これでTwitterにpostせずにTwitterクラスを使うコードをテストできる.
$ spec -cfs sample_tweet_spec.rb SampleTweet - should post "hoge" to twitter Finished in 0.003382 seconds 1 example, 0 failures
newを書き換えてモックのインスタンスを返すようにする点がRubyらしくて面白いと思う.