Skip to content

Commit

Permalink
Provide object_double alias for class_double.
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviershay committed Oct 22, 2013
1 parent 4932f3c commit 0f4c838
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 10 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Expand Up @@ -29,6 +29,7 @@ Enhancements:
ported from `rspec-fire` (Xavier Shay).
* `as_null_object` on a verifying double only responds to defined methods
(Xavier Shay).
* Provide `object_double` as an alias to `class_double` (Xavier Shay).
* Improved performance of double creation, particularly those with many
attributes. (Xavier Shay)
* Default value of `transfer_nested_constants` option for constant stubbing can
Expand Down
9 changes: 5 additions & 4 deletions features/verifying_doubles/class_doubles.feature
@@ -1,11 +1,12 @@
Feature: Using a class double

`class_double` is provided as a complement to `instance_double`, with the
difference that it verifies class methods on the given class rather than
instance methods.
`class_double` and `object_double` are provided as complements to
`instance_double`, with the difference that they verify instance methods on
the actual object assigned to the constant rather than the instance methods
of the given class. For classes, this is equivalent to the class methods.

In addition, it also provides a convenience method `as_stubbed_const` to
replace concrete classes with the defined double. See [mutating
replace concrete classes or constants with the defined double. See [mutating
constants](../mutating-constants) for more details.

Note: `class_double` can be used for modules as well. We chose to stick with
Expand Down
5 changes: 4 additions & 1 deletion lib/rspec/mocks/example_methods.rb
Expand Up @@ -54,11 +54,14 @@ def instance_double(doubled_class, *args)
# Constructs a test double against a specific class. If the given class
# name has been loaded, only class methods defined on the class are
# allowed to be stubbed. In all other ways it behaves like a
# [double](double).
# [double](double). This also works for stubbing constants, and is
# aliased as `object_double`..
def class_double(doubled_class, *args)
declare_verifying_double(ClassVerifyingDouble, doubled_class, *args)
end

alias_method :object_double, :class_double

# Disables warning messages about expectations being set on nil.
#
# By default warning messages are issued when expectations are set on
Expand Down
7 changes: 4 additions & 3 deletions lib/rspec/mocks/module_reference.rb
Expand Up @@ -10,17 +10,18 @@ def initialize(module_or_name)
case module_or_name
when Module then @module = module_or_name
when String then @name = module_or_name
when Object then @object = module_or_name
else raise ArgumentError,
"Module or String expected, got #{module_or_name.inspect}"
end
end

def defined?
!!original_module
@object || !!original_module
end

def name
@name ||= @module.name
@object || @name ||= @module.name
end

def when_loaded(&block)
Expand All @@ -30,7 +31,7 @@ def when_loaded(&block)
private

def original_module
@module ||= Constant.original(@name).original_value
@object || @module ||= Constant.original(@name).original_value
end
end
end
Expand Down
31 changes: 29 additions & 2 deletions spec/rspec/mocks/verifying_double_spec.rb
Expand Up @@ -3,6 +3,7 @@
class LoadedClass
M = :m
N = :n
INSTANCE = LoadedClass.new

def defined_instance_method; end
def self.defined_class_method; end
Expand Down Expand Up @@ -231,6 +232,33 @@ def prevents(&block)
end
end

describe 'const doubles' do
it 'replaces a constant and verifies instances methods' do
o = object_double("LoadedClass::INSTANCE").as_stubbed_const

expect(LoadedClass::INSTANCE).to eq(o)

prevents { expect(o).to receive(:undefined_instance_method) }
prevents { expect(o).to receive(:defined_class_method) }
prevents { o.defined_instance_method }

expect(o).to receive(:defined_instance_method)
o.defined_instance_method
end

it 'can create a double that matches the interface of any arbitrary object' do
o = object_double(LoadedClass.new)

prevents { expect(o).to receive(:undefined_instance_method) }
prevents { expect(o).to receive(:defined_class_method) }
prevents { o.defined_instance_method }

expect(o).to receive(:defined_instance_method)
o.defined_instance_method
end
end


describe 'when verify_doubled_constant_names config option is set' do
include_context "with isolated configuration"

Expand All @@ -251,8 +279,7 @@ def prevents(&block)
end
end

it 'can only be named with a string or a module' do
expect { instance_double(1) }.to raise_error(ArgumentError)
it 'can only be named with a string, object or a module' do
expect { instance_double(nil) }.to raise_error(ArgumentError)
end
end
Expand Down

0 comments on commit 0f4c838

Please sign in to comment.