メインコンテンツまでスキップ

部分的なテストダブル

部分的なテストダブル は、テストの文脈でテストダブルのような振る舞いを持つシステム内の実オブジェクトの拡張です。このテクニックは、Rubyでは非常に一般的です。なぜなら、クラスオブジェクトがメソッドのグローバルな名前空間として機能することがよくあるからです。例えば、Railsでは次のようになります:

person = double("person")
allow(Person).to receive(:find) { person }

この場合、Personをインストゥルメントして、find メッセージを受け取ったときに定義した person オブジェクトを返すようにしています。また、find が呼び出されない場合には、例が失敗するようにメッセージの期待値も設定できます:

person = double("person")
expect(Person).to receive(:find) { person }

RSpecは、スタブ化またはモック化しているメソッドを独自のテストダブルのようなメソッドで置き換えます。例の最後に、RSpecはメッセージの期待値を検証し、元のメソッドを復元します。

注意: verify_partial_doubles の設定オプションを有効にすることをおすすめします。

指定されたメソッドのみが再定義されます

次の内容で "partial_double_spec.rb" という名前のファイルがあるとします:

RSpec.describe "A partial double" do
# Note: stubbing a string like this is a terrible idea.
# This is just for demonstration purposes.
let(:string) { "a string" }
before { allow(string).to receive(:length).and_return(500) }

it "redefines the specified methods" do
expect(string.length).to eq(500)
end

it "does not effect other methods" do
expect(string.reverse).to eq("gnirts a")
end
end

rspec partial_double_spec.rb を実行すると、

すべての例がパスするはずです。

例が完了すると元のメソッドが復元されます

次の内容で "partial_double_spec.rb" という名前のファイルがあるとします:

class User
def self.find(id)
:original_return_value
end
end

RSpec.describe "A partial double" do
it "redefines a method" do
allow(User).to receive(:find).and_return(:redefined)
expect(User.find(3)).to eq(:redefined)
end

it "restores the redefined method after the example completes" do
expect(User.find(3)).to eq(:original_return_value)
end
end

rspec partial_double_spec.rb --order defined を実行すると、

すべての例がパスするはずです。