Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixing #67 - unstub support for any_instance

  • Loading branch information...
commit 0a7cde5ea217b4651761bb39ed8a4c3672972fc9 1 parent f04b8bb
@kaiwren kaiwren authored
View
44 features/method_stubs/any_instance.feature
@@ -56,4 +56,48 @@ Feature: stub on any instance of a class
end
"""
When I run `rspec example_spec.rb`
+ Then the examples should all pass
+
+ Scenario: any_instance unstub
+ Given a file named "example_spec.rb" with:
+ """
+ describe "any_instance.unstub" do
+ it "unstubs a stubbed method" do
+ class Object
+ def foo
+ :foo
+ end
+ end
+
+ Object.any_instance.stub(:foo)
+ Object.any_instance.unstub(:foo)
+
+ Object.new.foo.should eq(:foo)
+ end
+ end
+ """
+ When I run `rspec example_spec.rb`
+ Then the examples should all pass
+
+ Scenario: any_instance unstub
+ Given a file named "example_spec.rb" with:
+ """
+ describe "any_instance.unstub" do
+ context "with both an expectation and a stub already set" do
+ it "only removes the stub" do
+ class Object
+ def foo
+ :foo
+ end
+ end
+ Object.any_instance.should_receive(:foo).and_return(:bar)
+ Object.any_instance.stub(:foo)
+ Object.any_instance.unstub(:foo)
+
+ Object.new.foo.should eq(:bar)
+ end
+ end
+ end
+ """
+ When I run `rspec example_spec.rb`
Then the examples should all pass
View
2  features/support/env.rb
@@ -2,5 +2,5 @@
require 'rspec/expectations'
Before do
- @aruba_timeout_seconds = 5
+ RUBY_PLATFORM =~ /java/ ? @aruba_timeout_seconds = 60 : @aruba_timeout_seconds = 5
end
View
7 lib/rspec/mocks/any_instance/message_chains.rb
@@ -5,7 +5,12 @@ class MessageChains < Hash
def add(method_name, chain)
(self[method_name] ||= []) << chain
end
-
+
+ def remove_stub_chains_for!(method_name)
+ chains = self[method_name]
+ chains.reject! { |chain| chain.is_a?(StubChain) }
+ end
+
def has_expectation?(method_name)
!!self[method_name].find{|chain| chain.is_a?(ExpectationChain)}
end
View
8 lib/rspec/mocks/any_instance/recorder.rb
@@ -11,6 +11,14 @@ def initialize(klass)
@expectation_set = false
end
+ def unstub(method_name)
+ unless @observed_methods.include?(method_name.to_sym)
+ raise RSpec::Mocks::MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
+ end
+ message_chains.remove_stub_chains_for!(method_name)
+ stop_observing!(method_name) unless message_chains.has_expectation?(method_name)
+ end
+
def stub(method_name_or_method_map, *args, &block)
if method_name_or_method_map.is_a?(Hash)
method_map = method_name_or_method_map
View
9 spec/rspec/mocks/any_instance/message_chains_spec.rb
@@ -16,6 +16,15 @@
chains.has_expectation?(:method_name).should be_true
end
+ it "can remove all stub chains" do
+ chains.add(:method_name, stub_chain)
+ chains.add(:method_name, expectation_chain)
+ chains.add(:method_name, another_stub_chain = RSpec::Mocks::AnyInstance::StubChain.new)
+
+ chains.remove_stub_chains_for!(:method_name)
+ chains[:method_name].should eq([expectation_chain])
+ end
+
context "creating stub chains" do
it "understands how to add a stub chain for a method" do
chains.add(:method_name, stub_chain)
View
30 spec/rspec/mocks/any_instance_spec.rb
@@ -9,7 +9,7 @@ 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); :existing_method_with_arguments_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
@@ -212,7 +212,35 @@ class RSpec::SampleRspecTestClass;end
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' }
View
2  spec/rspec/mocks/failing_argument_matchers_spec.rb
@@ -87,7 +87,7 @@ module Mocks
expect do
@double.should_receive(:msg).with {|arg| arg.should eq :received }
@double.msg :no_msg_for_you
- end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected :received.*\s*.*got :no_msg_for_you/)
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected: :received.*\s*.*got: :no_msg_for_you/)
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.