Skip to content

Commit

Permalink
Allow both instance and class doubles for unloaded classes.
Browse files Browse the repository at this point in the history
Previously, if you used both fire_double("Foo") and fire_replaced_class_double("Foo"), and Foo was not defined, stubbing or mocking a method on the fire double would fail because ConstantStubber.original_value_for returned nil for "Foo" (since it was originally unloaded), but the constant lookup would succeed and it would try to verify the implementation against the class stub.

Now, ConstantStubber.find_original_value_for yields if the given class has been stubbed, and the value it yields can be nil if it was originally unloaded.  This allows us to support this edge case.
  • Loading branch information
myronmarston committed May 9, 2012
1 parent ee88a5d commit 02f3150
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
14 changes: 9 additions & 5 deletions lib/rspec/fire.rb
Expand Up @@ -135,9 +135,12 @@ def stub!(method_name)
end

def with_doubled_class
if original_stubbed_const_value = ConstantStubber.original_value_for(@__doubled_class_name)
yield original_stubbed_const_value
elsif recursive_const_defined?(@__doubled_class_name)
ConstantStubber.find_original_value_for(@__doubled_class_name) do |value|
yield value if value
return
end

if recursive_const_defined?(@__doubled_class_name)
yield recursive_const_get(@__doubled_class_name)
end
end
Expand Down Expand Up @@ -390,9 +393,10 @@ def self.stubbers
@stubbers ||= []
end

def self.original_value_for(constant_name)
def self.find_original_value_for(constant_name)
stubber = stubbers.find { |s| s.full_constant_name == constant_name }
stubber.original_value if stubber
yield stubber.original_value if stubber
self
end
end

Expand Down
22 changes: 22 additions & 0 deletions spec/fire_double_spec.rb
Expand Up @@ -270,6 +270,28 @@ def use_doubles(class_double, instance_double)
double.should_receive(:foo).with("a").and_return(:bar)
A::B::C.foo("a").should eq(:bar)
end

def use_doubles(class_double, instance_double)
instance_double.should_receive(:undefined_method).and_return(3)
class_double.should_receive(:undefined_method).and_return(4)

instance_double.undefined_method.should eq(3)
class_double.undefined_method.should eq(4)
end

it 'can be used after a declared fire_double for the same class' do
instance_double = fire_double("A::B::C")
class_double = fire_replaced_class_double("A::B::C")

use_doubles class_double, instance_double
end

it 'can be used before a declared fire_double for the same class' do
class_double = fire_replaced_class_double("A::B::C")
instance_double = fire_double("A::B::C")

use_doubles class_double, instance_double
end
end

shared_examples_for "loaded constant stubbing" do |const_name|
Expand Down

0 comments on commit 02f3150

Please sign in to comment.