rspec-mocks-diag 3.8.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +1108 -0
  5. data/LICENSE.md +25 -0
  6. data/README.md +460 -0
  7. data/lib/rspec/mocks.rb +130 -0
  8. data/lib/rspec/mocks/any_instance.rb +11 -0
  9. data/lib/rspec/mocks/any_instance/chain.rb +110 -0
  10. data/lib/rspec/mocks/any_instance/error_generator.rb +31 -0
  11. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +31 -0
  12. data/lib/rspec/mocks/any_instance/expectation_chain.rb +50 -0
  13. data/lib/rspec/mocks/any_instance/message_chains.rb +83 -0
  14. data/lib/rspec/mocks/any_instance/proxy.rb +116 -0
  15. data/lib/rspec/mocks/any_instance/recorder.rb +289 -0
  16. data/lib/rspec/mocks/any_instance/stub_chain.rb +51 -0
  17. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  18. data/lib/rspec/mocks/argument_list_matcher.rb +100 -0
  19. data/lib/rspec/mocks/argument_matchers.rb +320 -0
  20. data/lib/rspec/mocks/configuration.rb +212 -0
  21. data/lib/rspec/mocks/error_generator.rb +378 -0
  22. data/lib/rspec/mocks/example_methods.rb +434 -0
  23. data/lib/rspec/mocks/instance_method_stasher.rb +146 -0
  24. data/lib/rspec/mocks/marshal_extension.rb +41 -0
  25. data/lib/rspec/mocks/matchers/expectation_customization.rb +20 -0
  26. data/lib/rspec/mocks/matchers/have_received.rb +134 -0
  27. data/lib/rspec/mocks/matchers/receive.rb +132 -0
  28. data/lib/rspec/mocks/matchers/receive_message_chain.rb +82 -0
  29. data/lib/rspec/mocks/matchers/receive_messages.rb +77 -0
  30. data/lib/rspec/mocks/message_chain.rb +87 -0
  31. data/lib/rspec/mocks/message_expectation.rb +748 -0
  32. data/lib/rspec/mocks/method_double.rb +287 -0
  33. data/lib/rspec/mocks/method_reference.rb +202 -0
  34. data/lib/rspec/mocks/minitest_integration.rb +68 -0
  35. data/lib/rspec/mocks/mutate_const.rb +339 -0
  36. data/lib/rspec/mocks/object_reference.rb +149 -0
  37. data/lib/rspec/mocks/order_group.rb +81 -0
  38. data/lib/rspec/mocks/proxy.rb +485 -0
  39. data/lib/rspec/mocks/space.rb +238 -0
  40. data/lib/rspec/mocks/standalone.rb +3 -0
  41. data/lib/rspec/mocks/syntax.rb +325 -0
  42. data/lib/rspec/mocks/targets.rb +124 -0
  43. data/lib/rspec/mocks/test_double.rb +171 -0
  44. data/lib/rspec/mocks/verifying_double.rb +129 -0
  45. data/lib/rspec/mocks/verifying_message_expectation.rb +54 -0
  46. data/lib/rspec/mocks/verifying_proxy.rb +220 -0
  47. data/lib/rspec/mocks/version.rb +9 -0
  48. metadata +186 -0
@@ -0,0 +1,124 @@
1
+ module RSpec
2
+ module Mocks
3
+ # @private
4
+ module TargetDelegationClassMethods
5
+ def delegate_to(matcher_method)
6
+ define_method(:to) do |matcher, &block|
7
+ unless matcher_allowed?(matcher)
8
+ raise_unsupported_matcher(:to, matcher)
9
+ end
10
+ define_matcher(matcher, matcher_method, &block)
11
+ end
12
+ end
13
+
14
+ def delegate_not_to(matcher_method, options={})
15
+ method_name = options.fetch(:from)
16
+ define_method(method_name) do |matcher, &block|
17
+ case matcher
18
+ when Matchers::Receive, Matchers::HaveReceived
19
+ define_matcher(matcher, matcher_method, &block)
20
+ when Matchers::ReceiveMessages, Matchers::ReceiveMessageChain
21
+ raise_negation_unsupported(method_name, matcher)
22
+ else
23
+ raise_unsupported_matcher(method_name, matcher)
24
+ end
25
+ end
26
+ end
27
+
28
+ def disallow_negation(method_name)
29
+ define_method(method_name) do |matcher, *_args|
30
+ raise_negation_unsupported(method_name, matcher)
31
+ end
32
+ end
33
+ end
34
+
35
+ # @private
36
+ module TargetDelegationInstanceMethods
37
+ attr_reader :target
38
+
39
+ private
40
+
41
+ def matcher_allowed?(matcher)
42
+ Matchers::Matcher === matcher
43
+ end
44
+
45
+ def define_matcher(matcher, name, &block)
46
+ matcher.__send__(name, target, &block)
47
+ end
48
+
49
+ def raise_unsupported_matcher(method_name, matcher)
50
+ raise UnsupportedMatcherError,
51
+ "only the `receive`, `have_received` and `receive_messages` matchers are supported " \
52
+ "with `#{expression}(...).#{method_name}`, but you have provided: #{matcher}"
53
+ end
54
+
55
+ def raise_negation_unsupported(method_name, matcher)
56
+ raise NegationUnsupportedError,
57
+ "`#{expression}(...).#{method_name} #{matcher.name}` is not supported since it " \
58
+ "doesn't really make sense. What would it even mean?"
59
+ end
60
+ end
61
+
62
+ # @private
63
+ class TargetBase
64
+ def initialize(target)
65
+ @target = target
66
+ end
67
+
68
+ extend TargetDelegationClassMethods
69
+ include TargetDelegationInstanceMethods
70
+ end
71
+
72
+ # @private
73
+ module ExpectationTargetMethods
74
+ extend TargetDelegationClassMethods
75
+ include TargetDelegationInstanceMethods
76
+
77
+ delegate_to :setup_expectation
78
+ delegate_not_to :setup_negative_expectation, :from => :not_to
79
+ delegate_not_to :setup_negative_expectation, :from => :to_not
80
+
81
+ def expression
82
+ :expect
83
+ end
84
+ end
85
+
86
+ # @private
87
+ class ExpectationTarget < TargetBase
88
+ include ExpectationTargetMethods
89
+ end
90
+
91
+ # @private
92
+ class AllowanceTarget < TargetBase
93
+ def expression
94
+ :allow
95
+ end
96
+
97
+ delegate_to :setup_allowance
98
+ disallow_negation :not_to
99
+ disallow_negation :to_not
100
+ end
101
+
102
+ # @private
103
+ class AnyInstanceAllowanceTarget < TargetBase
104
+ def expression
105
+ :allow_any_instance_of
106
+ end
107
+
108
+ delegate_to :setup_any_instance_allowance
109
+ disallow_negation :not_to
110
+ disallow_negation :to_not
111
+ end
112
+
113
+ # @private
114
+ class AnyInstanceExpectationTarget < TargetBase
115
+ def expression
116
+ :expect_any_instance_of
117
+ end
118
+
119
+ delegate_to :setup_any_instance_expectation
120
+ delegate_not_to :setup_any_instance_negative_expectation, :from => :not_to
121
+ delegate_not_to :setup_any_instance_negative_expectation, :from => :to_not
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,171 @@
1
+ module RSpec
2
+ module Mocks
3
+ # Implements the methods needed for a pure test double. RSpec::Mocks::Double
4
+ # includes this module, and it is provided for cases where you want a
5
+ # pure test double without subclassing RSpec::Mocks::Double.
6
+ module TestDouble
7
+ # Creates a new test double with a `name` (that will be used in error
8
+ # messages only)
9
+ def initialize(name=nil, stubs={})
10
+ @__expired = false
11
+ if Hash === name && stubs.empty?
12
+ stubs = name
13
+ @name = nil
14
+ else
15
+ @name = name
16
+ end
17
+ assign_stubs(stubs)
18
+ end
19
+
20
+ # Tells the object to respond to all messages. If specific stub values
21
+ # are declared, they'll work as expected. If not, the receiver is
22
+ # returned.
23
+ def as_null_object
24
+ __mock_proxy.as_null_object
25
+ end
26
+
27
+ # Returns true if this object has received `as_null_object`
28
+ def null_object?
29
+ __mock_proxy.null_object?
30
+ end
31
+
32
+ # This allows for comparing the mock to other objects that proxy such as
33
+ # ActiveRecords belongs_to proxy objects. By making the other object run
34
+ # the comparison, we're sure the call gets delegated to the proxy
35
+ # target.
36
+ def ==(other)
37
+ other == __mock_proxy
38
+ end
39
+
40
+ # @private
41
+ def inspect
42
+ TestDoubleFormatter.format(self)
43
+ end
44
+
45
+ # @private
46
+ def to_s
47
+ inspect.tr('<', '[').tr('>', ']')
48
+ end
49
+
50
+ # @private
51
+ def respond_to?(message, incl_private=false)
52
+ __mock_proxy.null_object? ? true : super
53
+ end
54
+
55
+ # @private
56
+ def __build_mock_proxy_unless_expired(order_group)
57
+ __raise_expired_error || __build_mock_proxy(order_group)
58
+ end
59
+
60
+ # @private
61
+ def __disallow_further_usage!
62
+ @__expired = true
63
+ end
64
+
65
+ # Override for default freeze implementation to prevent freezing of test
66
+ # doubles.
67
+ def freeze
68
+ RSpec.warn_with("WARNING: you attempted to freeze a test double. This is explicitly a no-op as freezing doubles can lead to undesired behaviour when resetting tests.")
69
+ self
70
+ end
71
+
72
+ private
73
+
74
+ def method_missing(message, *args, &block)
75
+ proxy = __mock_proxy
76
+ proxy.record_message_received(message, *args, &block)
77
+
78
+ if proxy.null_object?
79
+ case message
80
+ when :to_int then return 0
81
+ when :to_a, :to_ary then return nil
82
+ when :to_str then return to_s
83
+ else return self
84
+ end
85
+ end
86
+
87
+ # Defined private and protected methods will still trigger `method_missing`
88
+ # when called publicly. We want ruby's method visibility error to get raised,
89
+ # so we simply delegate to `super` in that case.
90
+ # ...well, we would delegate to `super`, but there's a JRuby
91
+ # bug, so we raise our own visibility error instead:
92
+ # https://github.com/jruby/jruby/issues/1398
93
+ visibility = proxy.visibility_for(message)
94
+ if visibility == :private || visibility == :protected
95
+ ErrorGenerator.new(self).raise_non_public_error(
96
+ message, visibility
97
+ )
98
+ end
99
+
100
+ # Required wrapping doubles in an Array on Ruby 1.9.2
101
+ raise NoMethodError if [:to_a, :to_ary].include? message
102
+ proxy.raise_unexpected_message_error(message, args)
103
+ end
104
+
105
+ def assign_stubs(stubs)
106
+ stubs.each_pair do |message, response|
107
+ __mock_proxy.add_simple_stub(message, response)
108
+ end
109
+ end
110
+
111
+ def __mock_proxy
112
+ ::RSpec::Mocks.space.proxy_for(self)
113
+ end
114
+
115
+ def __build_mock_proxy(order_group)
116
+ TestDoubleProxy.new(self, order_group)
117
+ end
118
+
119
+ def __raise_expired_error
120
+ return false unless @__expired
121
+ ErrorGenerator.new(self).raise_expired_test_double_error
122
+ end
123
+
124
+ def initialize_copy(other)
125
+ as_null_object if other.null_object?
126
+ super
127
+ end
128
+ end
129
+
130
+ # A generic test double object. `double`, `instance_double` and friends
131
+ # return an instance of this.
132
+ class Double
133
+ include TestDouble
134
+ end
135
+
136
+ # @private
137
+ module TestDoubleFormatter
138
+ def self.format(dbl, unwrap=false)
139
+ format = "#{type_desc(dbl)}#{verified_module_desc(dbl)} #{name_desc(dbl)}"
140
+ return format if unwrap
141
+ "#<#{format}>"
142
+ end
143
+
144
+ class << self
145
+ private
146
+
147
+ def type_desc(dbl)
148
+ case dbl
149
+ when InstanceVerifyingDouble then "InstanceDouble"
150
+ when ClassVerifyingDouble then "ClassDouble"
151
+ when ObjectVerifyingDouble then "ObjectDouble"
152
+ else "Double"
153
+ end
154
+ end
155
+
156
+ # @private
157
+ IVAR_GET = Object.instance_method(:instance_variable_get)
158
+
159
+ def verified_module_desc(dbl)
160
+ return nil unless VerifyingDouble === dbl
161
+ "(#{IVAR_GET.bind(dbl).call(:@doubled_module).description})"
162
+ end
163
+
164
+ def name_desc(dbl)
165
+ return "(anonymous)" unless (name = IVAR_GET.bind(dbl).call(:@name))
166
+ name.inspect
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,129 @@
1
+ RSpec::Support.require_rspec_mocks 'verifying_proxy'
2
+
3
+ module RSpec
4
+ module Mocks
5
+ # @private
6
+ module VerifyingDouble
7
+ def respond_to?(message, include_private=false)
8
+ return super unless null_object?
9
+
10
+ method_ref = __mock_proxy.method_reference[message]
11
+
12
+ case method_ref.visibility
13
+ when :public then true
14
+ when :private then include_private
15
+ when :protected then include_private || RUBY_VERSION.to_f < 2.0
16
+ else !method_ref.unimplemented?
17
+ end
18
+ end
19
+
20
+ def method_missing(message, *args, &block)
21
+ # Null object conditional is an optimization. If not a null object,
22
+ # validity of method expectations will have been checked at definition
23
+ # time.
24
+ if null_object?
25
+ if @__sending_message == message
26
+ __mock_proxy.ensure_implemented(message)
27
+ else
28
+ __mock_proxy.ensure_publicly_implemented(message, self)
29
+ end
30
+
31
+ __mock_proxy.validate_arguments!(message, args)
32
+ end
33
+
34
+ super
35
+ end
36
+
37
+ # @private
38
+ module SilentIO
39
+ def self.method_missing(*); end
40
+ def self.respond_to?(*)
41
+ true
42
+ end
43
+ end
44
+
45
+ # Redefining `__send__` causes ruby to issue a warning.
46
+ old, $stderr = $stderr, SilentIO
47
+ def __send__(name, *args, &block)
48
+ @__sending_message = name
49
+ super
50
+ ensure
51
+ @__sending_message = nil
52
+ end
53
+ $stderr = old
54
+
55
+ def send(name, *args, &block)
56
+ __send__(name, *args, &block)
57
+ end
58
+
59
+ def initialize(doubled_module, *args)
60
+ @doubled_module = doubled_module
61
+
62
+ possible_name = args.first
63
+ name = if String === possible_name || Symbol === possible_name
64
+ args.shift
65
+ end
66
+
67
+ super(name, *args)
68
+ @__sending_message = nil
69
+ end
70
+ end
71
+
72
+ # A mock providing a custom proxy that can verify the validity of any
73
+ # method stubs or expectations against the public instance methods of the
74
+ # given class.
75
+ #
76
+ # @private
77
+ class InstanceVerifyingDouble
78
+ include TestDouble
79
+ include VerifyingDouble
80
+
81
+ def __build_mock_proxy(order_group)
82
+ VerifyingProxy.new(self, order_group,
83
+ @doubled_module,
84
+ InstanceMethodReference
85
+ )
86
+ end
87
+ end
88
+
89
+ # An awkward module necessary because we cannot otherwise have
90
+ # ClassVerifyingDouble inherit from Module and still share these methods.
91
+ #
92
+ # @private
93
+ module ObjectVerifyingDoubleMethods
94
+ include TestDouble
95
+ include VerifyingDouble
96
+
97
+ def as_stubbed_const(options={})
98
+ ConstantMutator.stub(@doubled_module.const_to_replace, self, options)
99
+ self
100
+ end
101
+
102
+ private
103
+
104
+ def __build_mock_proxy(order_group)
105
+ VerifyingProxy.new(self, order_group,
106
+ @doubled_module,
107
+ ObjectMethodReference
108
+ )
109
+ end
110
+ end
111
+
112
+ # Similar to an InstanceVerifyingDouble, except that it verifies against
113
+ # public methods of the given object.
114
+ #
115
+ # @private
116
+ class ObjectVerifyingDouble
117
+ include ObjectVerifyingDoubleMethods
118
+ end
119
+
120
+ # Effectively the same as an ObjectVerifyingDouble (since a class is a type
121
+ # of object), except with Module in the inheritance chain so that
122
+ # transferring nested constants to work.
123
+ #
124
+ # @private
125
+ class ClassVerifyingDouble < Module
126
+ include ObjectVerifyingDoubleMethods
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,54 @@
1
+ RSpec::Support.require_rspec_support 'method_signature_verifier'
2
+
3
+ module RSpec
4
+ module Mocks
5
+ # A message expectation that knows about the real implementation of the
6
+ # message being expected, so that it can verify that any expectations
7
+ # have the valid arguments.
8
+ # @api private
9
+ class VerifyingMessageExpectation < MessageExpectation
10
+ # A level of indirection is used here rather than just passing in the
11
+ # method itself, since method look up is expensive and we only want to
12
+ # do it if actually needed.
13
+ #
14
+ # Conceptually the method reference makes more sense as a constructor
15
+ # argument since it should be immutable, but it is significantly more
16
+ # straight forward to build the object in pieces so for now it stays as
17
+ # an accessor.
18
+ attr_accessor :method_reference
19
+
20
+ def initialize(*args)
21
+ super
22
+ end
23
+
24
+ # @private
25
+ def with(*args, &block)
26
+ super(*args, &block).tap do
27
+ validate_expected_arguments! do |signature|
28
+ example_call_site_args = [:an_arg] * signature.min_non_kw_args
29
+ example_call_site_args << :kw_args_hash if signature.required_kw_args.any?
30
+ @argument_list_matcher.resolve_expected_args_based_on(example_call_site_args)
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def validate_expected_arguments!
38
+ return if method_reference.nil?
39
+
40
+ method_reference.with_signature do |signature|
41
+ args = yield signature
42
+ verifier = Support::LooseSignatureVerifier.new(signature, args)
43
+
44
+ unless verifier.valid?
45
+ # Fail fast is required, otherwise the message expectation will fail
46
+ # as well ("expected method not called") and clobber this one.
47
+ @failed_fast = true
48
+ @error_generator.raise_invalid_arguments_error(verifier)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end