Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Verifying null objects only respond to defined methods.

* Delegated logic from the double to the proxy, since it is near by and
  already knows how to check if a method is implemented.
* No additional documentation, since this is the least surprising
  behaviour.
* Not sufficient duplication to warrant DRYing up the verifying method_missing
  implementations, if these classes start to look any more alike I would
  consider it though.
* verify_method_missing is a terrible method name, but I wanted to tell
  rather than ask rather than including the null object conditional in
  the method_missing implementation.

Fixes #392.
  • Loading branch information...
commit d9121a2fd7751bf959d97dd2e5173d512f9ba348 1 parent 331b4b3
@xaviershay authored
View
10 lib/rspec/mocks/verifying_double.rb
@@ -23,6 +23,11 @@ def __build_mock_proxy
:instance_method
)
end
+
+ def method_missing(message, *args, &block)
+ __mock_proxy.verify_method_missing(message)
+ super
+ end
end
# Similar to an InstanceVerifyingMock, except that it verifies against
@@ -51,6 +56,11 @@ def as_stubbed_const(options = {})
ConstantMutator.stub(@doubled_module.name, self, options)
self
end
+
+ def method_missing(message, *args, &block)
+ __mock_proxy.verify_method_missing(message)
+ super
+ end
end
end
View
7 lib/rspec/mocks/verifying_proxy.rb
@@ -41,6 +41,13 @@ def add_message_expectation(location, method_name, opts={}, &block)
super
end
+ def verify_method_missing(message)
+ # Null object conditional is an optimization. If not a null object,
+ # validity of method expectations will have been checked at definition
+ # time.
+ ensure_implemented(message) if null_object?
+ end
+
# A custom method double is required to pass through a way to lookup
# methods to determine their arity. This is only relevant if the doubled
# class is loaded.
View
14 spec/rspec/mocks/verifying_double_spec.rb
@@ -107,6 +107,13 @@ def prevents(&block)
o = instance_double(LoadedClass, :defined_instance_method => 1)
expect(o.defined_instance_method).to eq(1)
end
+
+ it 'only allows defined methods for null objects' do
+ o = instance_double('LoadedClass').as_null_object
+
+ expect(o.defined_instance_method).to eq(o)
+ prevents { o.undefined_method }
+ end
end
end
@@ -186,6 +193,13 @@ def prevents(&block)
expect(dbl1).to receive(:undefined_class_method)
}
end
+
+ it 'only allows defined methods for null objects' do
+ o = class_double('LoadedClass').as_null_object
+
+ expect(o.defined_class_method).to eq(o)
+ prevents { o.undefined_method }
+ end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.