Skip to content

Commit

Permalink
Use original const value when checking implementation for fire_double.
Browse files Browse the repository at this point in the history
This allows fire_double and fire_replaced_class_double to both
be used in the same example with the same doubled class.
  • Loading branch information
myronmarston committed Mar 28, 2012
1 parent 1b3ba96 commit e8d09c0
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 12 deletions.
33 changes: 30 additions & 3 deletions lib/rspec/fire.rb
Expand Up @@ -131,7 +131,9 @@ def stub(method_name)
end

def with_doubled_class
if recursive_const_defined?(@__doubled_class_name)
if original_stubbed_const_value = ConstantStubber.original_value_for(@__doubled_class_name)
yield original_stubbed_const_value
elsif recursive_const_defined?(@__doubled_class_name)
yield recursive_const_get(@__doubled_class_name)
end
end
Expand Down Expand Up @@ -243,7 +245,7 @@ class ConstantStubber

class DefinedConstantReplacer
include RecursiveConstMethods
attr_reader :original_value
attr_reader :original_value, :full_constant_name

def initialize(full_constant_name, stubbed_value, transfer_nested_constants)
@full_constant_name = full_constant_name
Expand Down Expand Up @@ -312,6 +314,8 @@ def verify_constants_to_transfer!
class UndefinedConstantSetter
include RecursiveConstMethods

attr_reader :full_constant_name

def initialize(full_constant_name, stubbed_value)
@full_constant_name = full_constant_name
@stubbed_value = stubbed_value
Expand Down Expand Up @@ -354,10 +358,33 @@ def self.stub!(constant_name, value, options = {})
UndefinedConstantSetter.new(constant_name, value)
end

stubbers << stubber

stubber.stub!
::RSpec::Mocks.space.add(stubber)
ensure_registered_with_rspec_mocks
stubber.original_value
end

def self.ensure_registered_with_rspec_mocks
return if @registered_with_rspec_mocks
::RSpec::Mocks.space.add(self)
@registered_with_rspec_mocks = true
end

def self.rspec_reset
@registered_with_rspec_mocks = false
stubbers.each { |s| s.rspec_reset }
stubbers.clear
end

def self.stubbers
@stubbers ||= []
end

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

def stub_const(name, value, options = {})
Expand Down
36 changes: 27 additions & 9 deletions spec/fire_double_spec.rb
Expand Up @@ -5,14 +5,6 @@ def use; end

TOP_LEVEL_VALUE_CONST = 7

RSpec::Mocks::Space.class_eval do
# Deal with the fact that #mocks was renamed to #receivers for RSpec 2.9:
# https://github.com/rspec/rspec-mocks/commit/17c259ea5143d309e90ca6d53d40f6356ac2d0a5
unless private_instance_methods.map(&:to_sym).include?(:receivers)
alias_method :receivers, :mocks
end
end

module TestMethods
def defined_method
raise "Y U NO MOCK?"
Expand All @@ -28,6 +20,7 @@ class TestObject
end

class TestClass
include TestMethods
extend TestMethods

M = :m
Expand Down Expand Up @@ -242,6 +235,31 @@ def reset_rspec_mocks
TestClass::M.should eq(:m)
TestClass::N.should eq(:n)
end

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

instance_double.defined_method.should eq(3)
class_double.defined_method.should eq(4)

expect { instance_double.should_receive(:undefined_method) }.to fail_matching("does not implement")
expect { class_double.should_receive(:undefined_method) }.to fail_matching("does not implement")
end

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

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("TestClass")
instance_double = fire_double("TestClass")

use_doubles class_double, instance_double
end
end

describe '#fire_replaced_class_double (for a non-existant class)' do
Expand Down Expand Up @@ -337,7 +355,7 @@ def change_const_value_to(value)
it 'does not remove the constant when the example manually sets it' do
begin
stub_const(const_name, 7)
stubber = RSpec::Mocks.space.send(:receivers).first
stubber = RSpec::Fire::ConstantStubber.stubbers.first
change_const_value_to(new_const_value = Object.new)
reset_rspec_mocks
const.should equal(new_const_value)
Expand Down

0 comments on commit e8d09c0

Please sign in to comment.