spec/rspec/mocks/any_instance_spec.rb in rspec-mocks-2.6.0 vs spec/rspec/mocks/any_instance_spec.rb in rspec-mocks-2.7.0.rc1
- old
+ new
@@ -1,15 +1,17 @@
+
require 'spec_helper'
module RSpec
module Mocks
describe "#any_instance" do
class CustomErrorForAnyInstanceSpec < StandardError;end
let(:klass) do
Class.new do
def existing_method; :existing_method_return_value; end
+ def existing_method_with_arguments(arg_one, arg_two = nil); :existing_method_with_arguments_return_value; end
def another_existing_method; end
end
end
let(:existing_method_return_value){ :existing_method_return_value }
@@ -29,11 +31,17 @@
it "raises an error if 'with' follows 'and_yield'" do
lambda{ klass.any_instance.stub(:foo).and_yield(1).with("1") }.should raise_error(NoMethodError)
end
end
-
+
+ context "#stub_chain" do
+ it "raises an error if 'stub_chain' follows 'any_instance'" do
+ lambda{ klass.any_instance.and_return("1").stub_chain(:foo, :bar) }.should raise_error(NoMethodError)
+ end
+ end
+
context "#should_receive" do
it "raises an error if 'should_receive' follows 'with'" do
lambda{ klass.any_instance.with("1").should_receive(:foo) }.should raise_error(NoMethodError)
end
@@ -46,17 +54,48 @@
pending "see Github issue #42"
lambda{ klass.any_instance.should_receive(:foo).and_raise(1).with("1") }.should raise_error(NoMethodError)
end
end
end
-
+
context "with #stub" do
it "does not suppress an exception when a method that doesn't exist is invoked" do
klass.any_instance.stub(:foo)
lambda{ klass.new.bar }.should raise_error(NoMethodError)
end
+
+ context 'multiple methods' do
+ it "allows multiple methods to be stubbed in a single invocation" do
+ klass.any_instance.stub(:foo => 'foo', :bar => 'bar')
+ instance = klass.new
+ instance.foo.should eq('foo')
+ instance.bar.should eq('bar')
+ end
+
+ it "adheres to the contract of multiple method stubbing withou any instance" do
+ Object.new.stub(:foo => 'foo', :bar => 'bar').should eq(:foo => 'foo', :bar => 'bar')
+ klass.any_instance.stub(:foo => 'foo', :bar => 'bar').should eq(:foo => 'foo', :bar => 'bar')
+ end
+
+ context "allows a chain of methods to be stubbed using #stub_chain" do
+ it "given symbols representing the methods" do
+ klass.any_instance.stub_chain(:one, :two, :three).and_return(:four)
+ klass.new.one.two.three.should eq(:four)
+ end
+ it "given a hash as the last argument uses the value as the expected return value" do
+ klass.any_instance.stub_chain(:one, :two, :three => :four)
+ klass.new.one.two.three.should eq(:four)
+ end
+
+ it "given a string of '.' separated method names representing the chain" do
+ klass.any_instance.stub_chain('one.two.three').and_return(:four)
+ klass.new.one.two.three.should eq(:four)
+ end
+ end
+ end
+
context "behaves as 'every instance'" do
it "stubs every instance in the spec" do
klass.any_instance.stub(:foo).and_return(result = Object.new)
klass.new.foo.should eq(result)
klass.new.foo.should eq(result)
@@ -66,11 +105,48 @@
instance = klass.new
klass.any_instance.stub(:foo).and_return(result = Object.new)
instance.foo.should eq(result)
end
end
+
+ context "with argument matching" do
+ before do
+ klass.any_instance.stub(:foo).with(:param_one, :param_two).and_return(:result_one)
+ klass.any_instance.stub(:foo).with(:param_three, :param_four).and_return(:result_two)
+ end
+
+ it "returns the stubbed value when arguments match" do
+ instance = klass.new
+ instance.foo(:param_one, :param_two).should eq(:result_one)
+ instance.foo(:param_three, :param_four).should eq(:result_two)
+ end
+ it "fails the spec with an expectation error when the arguments do not match" do
+ expect do
+ klass.new.foo(:param_one, :param_three)
+ end.to(raise_error(RSpec::Mocks::MockExpectationError))
+ end
+ end
+
+ context "with multiple stubs" do
+ before do
+ klass.any_instance.stub(:foo).and_return(1)
+ klass.any_instance.stub(:bar).and_return(2)
+ end
+
+ it "stubs a method" do
+ instance = klass.new
+ instance.foo.should eq(1)
+ instance.bar.should eq(2)
+ end
+
+ it "returns the same value for calls on different instances" do
+ klass.new.foo.should eq(klass.new.foo)
+ klass.new.bar.should eq(klass.new.bar)
+ end
+ end
+
context "with #and_return" do
it "stubs a method that doesn't exist" do
klass.any_instance.stub(:foo).and_return(1)
klass.new.foo.should eq(1)
end
@@ -157,11 +233,39 @@
class RSpec::SampleRspecTestClass;end
RSpec::SampleRspecTestClass.foo.should eq(1)
end
end
end
+
+ context "unstub implementation" do
+ it "replaces the stubbed method with the original method" do
+ klass.any_instance.stub(:existing_method)
+ klass.any_instance.unstub(:existing_method)
+ klass.new.existing_method.should eq(:existing_method_return_value)
+ end
+ it "removes all stubs with the supplied method name" do
+ klass.any_instance.stub(:existing_method).with(1)
+ klass.any_instance.stub(:existing_method).with(2)
+ klass.any_instance.unstub(:existing_method)
+ klass.new.existing_method.should eq(:existing_method_return_value)
+ end
+
+ it "does not remove any expectations with the same method name" do
+ klass.any_instance.should_receive(:existing_method_with_arguments).with(3).and_return(:three)
+ klass.any_instance.stub(:existing_method_with_arguments).with(1)
+ klass.any_instance.stub(:existing_method_with_arguments).with(2)
+ klass.any_instance.unstub(:existing_method_with_arguments)
+ klass.new.existing_method_with_arguments(3).should eq :three
+ end
+
+ it "raises a MockExpectationError if the method has not been stubbed" do
+ lambda do
+ klass.any_instance.unstub(:existing_method)
+ end.should raise_error(RSpec::Mocks::MockExpectationError, 'The method `existing_method` was not stubbed or was already unstubbed')
+ end
+ end
context "with #should_receive" do
let(:foo_expectation_error_message) { 'Exactly one instance should have received the following message(s) but didn\'t: foo' }
let(:existing_method_expectation_error_message) { 'Exactly one instance should have received the following message(s) but didn\'t: existing_method' }
context "with an expectation is set on a method which does not exist" do
@@ -287,9 +391,50 @@
instance_one.existing_method
instance_two.existing_method
end.to raise_error(RSpec::Mocks::MockExpectationError, "The message 'existing_method' was received by #{instance_two.inspect} but has already been received by #{instance_one.inspect}")
end
+ end
+ end
+
+ context "with argument matching" do
+ before do
+ klass.any_instance.should_receive(:foo).with(:param_one, :param_two).and_return(:result_one)
+ klass.any_instance.should_receive(:foo).with(:param_three, :param_four).and_return(:result_two)
+ end
+
+ it "returns the expected value when arguments match" do
+ instance = klass.new
+ instance.foo(:param_one, :param_two).should eq(:result_one)
+ instance.foo(:param_three, :param_four).should eq(:result_two)
+ end
+
+ it "fails when the arguments match but different instances are used" do
+ instances = Array.new(2) { klass.new }
+ expect do
+ instances[0].foo(:param_one, :param_two).should eq(:result_one)
+ instances[1].foo(:param_three, :param_four).should eq(:result_two)
+ end.to raise_error(RSpec::Mocks::MockExpectationError)
+
+ # ignore the fact that should_receive expectations were not met
+ instances.each { |instance| instance.rspec_reset }
+ end
+
+ it "is not affected by the invocation of existing methods on other instances" do
+ klass.new.existing_method_with_arguments(:param_one, :param_two).should eq(:existing_method_with_arguments_return_value)
+ instance = klass.new
+ instance.foo(:param_one, :param_two).should eq(:result_one)
+ instance.foo(:param_three, :param_four).should eq(:result_two)
+ end
+
+ it "fails when arguments do not match" do
+ instance = klass.new
+ expect do
+ instance.foo(:param_one, :param_three)
+ end.to raise_error(RSpec::Mocks::MockExpectationError)
+
+ # ignore the fact that should_receive expectations were not met
+ instance.rspec_reset
end
end
context "message count" do
context "the 'once' constraint" do