Permalink
Browse files

Verifying null objects only respond to defined methods.

* No additional documentation, since this is the least surprising
  behaviour.

Fixes #392.
  • Loading branch information...
xaviershay committed Sep 25, 2013
1 parent 331b4b3 commit 538f5243e014e52f37910b6199ee51847ac4b9f5
View
@@ -26,6 +26,8 @@ Enhancements:
* Yield the receiver to `any_instance` implementation blocks (Sam Phippen).
* Provide `instance_double` and `class_double` to create verifying doubles,
ported from `rspec-fire` (Xavier Shay).
+* `as_null_object` on a verifying double only responds to defined methods
+ (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
@@ -4,11 +4,22 @@
module RSpec
module Mocks
+ module VerifyingDouble
+ def method_missing(message, *args, &block)
+ # Null object conditional is an optimization. If not a null object,
+ # validity of method expectations will have been checked at definition
+ # time.
+ __mock_proxy.ensure_implemented(message) if null_object?
+ super
+ end
+ end
+
# A mock providing a custom proxy that can verify the validity of any
# method stubs or expectations against the public instance methods of the
# given class.
class InstanceVerifyingMock
include TestDouble
+ include VerifyingDouble
def initialize(doubled_module, *args)
@doubled_module = doubled_module
@@ -32,6 +43,7 @@ def __build_mock_proxy
# constants to work.
class ClassVerifyingMock < Module
include TestDouble
+ include VerifyingDouble
def initialize(doubled_module, *args)
@doubled_module = doubled_module
@@ -58,8 +58,6 @@ def method_double
end
end
- protected
-
def ensure_implemented(method_name)
@doubled_module.when_loaded do |original_module|
unless original_module.__send__(@method_checker, method_name)
@@ -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

0 comments on commit 538f524

Please sign in to comment.