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,130 @@
1
+ require 'rspec/support'
2
+ RSpec::Support.require_rspec_support 'caller_filter'
3
+ RSpec::Support.require_rspec_support 'warnings'
4
+ RSpec::Support.require_rspec_support 'ruby_features'
5
+
6
+ RSpec::Support.define_optimized_require_for_rspec(:mocks) { |f| require_relative f }
7
+
8
+ %w[
9
+ instance_method_stasher
10
+ method_double
11
+ argument_matchers
12
+ example_methods
13
+ proxy
14
+ test_double
15
+ argument_list_matcher
16
+ message_expectation
17
+ order_group
18
+ error_generator
19
+ space
20
+ mutate_const
21
+ targets
22
+ syntax
23
+ configuration
24
+ verifying_double
25
+ version
26
+ ].each { |name| RSpec::Support.require_rspec_mocks name }
27
+
28
+ # Share the top-level RSpec namespace, because we are a core supported
29
+ # extension.
30
+ module RSpec
31
+ # Contains top-level utility methods. While this contains a few
32
+ # public methods, these are not generally meant to be called from
33
+ # a test or example. They exist primarily for integration with
34
+ # test frameworks (such as rspec-core).
35
+ module Mocks
36
+ # Performs per-test/example setup. This should be called before
37
+ # an test or example begins.
38
+ def self.setup
39
+ @space_stack << (@space = space.new_scope)
40
+ end
41
+
42
+ # Verifies any message expectations that were set during the
43
+ # test or example. This should be called at the end of an example.
44
+ def self.verify
45
+ space.verify_all
46
+ end
47
+
48
+ # Cleans up all test double state (including any methods that were
49
+ # redefined on partial doubles). This _must_ be called after
50
+ # each example, even if an error was raised during the example.
51
+ def self.teardown
52
+ space.reset_all
53
+ @space_stack.pop
54
+ @space = @space_stack.last || @root_space
55
+ end
56
+
57
+ # Adds an allowance (stub) on `subject`
58
+ #
59
+ # @param subject the subject to which the message will be added
60
+ # @param message a symbol, representing the message that will be
61
+ # added.
62
+ # @param opts a hash of options, :expected_from is used to set the
63
+ # original call site
64
+ # @yield an optional implementation for the allowance
65
+ #
66
+ # @example Defines the implementation of `foo` on `bar`, using the passed block
67
+ # x = 0
68
+ # RSpec::Mocks.allow_message(bar, :foo) { x += 1 }
69
+ def self.allow_message(subject, message, opts={}, &block)
70
+ space.proxy_for(subject).add_stub(message, opts, &block)
71
+ end
72
+
73
+ # Sets a message expectation on `subject`.
74
+ # @param subject the subject on which the message will be expected
75
+ # @param message a symbol, representing the message that will be
76
+ # expected.
77
+ # @param opts a hash of options, :expected_from is used to set the
78
+ # original call site
79
+ # @yield an optional implementation for the expectation
80
+ #
81
+ # @example Expect the message `foo` to receive `bar`, then call it
82
+ # RSpec::Mocks.expect_message(bar, :foo)
83
+ # bar.foo
84
+ def self.expect_message(subject, message, opts={}, &block)
85
+ space.proxy_for(subject).add_message_expectation(message, opts, &block)
86
+ end
87
+
88
+ # Call the passed block and verify mocks after it has executed. This allows
89
+ # mock usage in arbitrary places, such as a `before(:all)` hook.
90
+ def self.with_temporary_scope
91
+ setup
92
+
93
+ begin
94
+ yield
95
+ verify
96
+ ensure
97
+ teardown
98
+ end
99
+ end
100
+
101
+ class << self
102
+ # @private
103
+ attr_reader :space
104
+ end
105
+ @space_stack = []
106
+ @root_space = @space = RSpec::Mocks::RootSpace.new
107
+
108
+ # @private
109
+ IGNORED_BACKTRACE_LINE = 'this backtrace line is ignored'
110
+
111
+ # To speed up boot time a bit, delay loading optional or rarely
112
+ # used features until their first use.
113
+ autoload :AnyInstance, "rspec/mocks/any_instance"
114
+ autoload :ExpectChain, "rspec/mocks/message_chain"
115
+ autoload :StubChain, "rspec/mocks/message_chain"
116
+ autoload :MarshalExtension, "rspec/mocks/marshal_extension"
117
+
118
+ # Namespace for mock-related matchers.
119
+ module Matchers
120
+ # @private
121
+ # just a "tag" for rspec-mock matchers detection
122
+ module Matcher; end
123
+
124
+ autoload :HaveReceived, "rspec/mocks/matchers/have_received"
125
+ autoload :Receive, "rspec/mocks/matchers/receive"
126
+ autoload :ReceiveMessageChain, "rspec/mocks/matchers/receive_message_chain"
127
+ autoload :ReceiveMessages, "rspec/mocks/matchers/receive_messages"
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,11 @@
1
+ %w[
2
+ any_instance/chain
3
+ any_instance/error_generator
4
+ any_instance/stub_chain
5
+ any_instance/stub_chain_chain
6
+ any_instance/expect_chain_chain
7
+ any_instance/expectation_chain
8
+ any_instance/message_chains
9
+ any_instance/recorder
10
+ any_instance/proxy
11
+ ].each { |f| RSpec::Support.require_rspec_mocks(f) }
@@ -0,0 +1,110 @@
1
+ module RSpec
2
+ module Mocks
3
+ # @private
4
+ module AnyInstance
5
+ # @private
6
+ class Chain
7
+ def initialize(recorder, *args, &block)
8
+ @recorder = recorder
9
+ @expectation_args = args
10
+ @expectation_block = block
11
+ @argument_list_matcher = ArgumentListMatcher::MATCH_ALL
12
+ end
13
+
14
+ # @private
15
+ #
16
+ # Provides convenience methods for recording customizations on message
17
+ # expectations.
18
+ module Customizations
19
+ # @macro [attach] record
20
+ # @method $1(*args, &block)
21
+ # Records the `$1` message for playback against an instance that
22
+ # invokes a method stubbed or mocked using `any_instance`.
23
+ #
24
+ # @see RSpec::Mocks::MessageExpectation#$1
25
+ #
26
+ def self.record(method_name)
27
+ define_method(method_name) do |*args, &block|
28
+ record(method_name, *args, &block)
29
+ end
30
+ end
31
+
32
+ record :and_return
33
+ record :and_raise
34
+ record :and_throw
35
+ record :and_yield
36
+ record :and_call_original
37
+ record :and_wrap_original
38
+ record :with
39
+ record :once
40
+ record :twice
41
+ record :thrice
42
+ record :exactly
43
+ record :times
44
+ record :never
45
+ record :at_least
46
+ record :at_most
47
+ end
48
+
49
+ include Customizations
50
+
51
+ # @private
52
+ def playback!(instance)
53
+ message_expectation = create_message_expectation_on(instance)
54
+ messages.inject(message_expectation) do |object, message|
55
+ object.__send__(*message.first, &message.last)
56
+ end
57
+ end
58
+
59
+ # @private
60
+ def constrained_to_any_of?(*constraints)
61
+ constraints.any? do |constraint|
62
+ messages.any? do |message|
63
+ message.first.first == constraint
64
+ end
65
+ end
66
+ end
67
+
68
+ # @private
69
+ def matches_args?(*args)
70
+ @argument_list_matcher.args_match?(*args)
71
+ end
72
+
73
+ # @private
74
+ def expectation_fulfilled!
75
+ @expectation_fulfilled = true
76
+ end
77
+
78
+ def never
79
+ AnyInstance.error_generator.raise_double_negation_error("expect_any_instance_of(MyClass)") if negated?
80
+ super
81
+ end
82
+
83
+ def with(*args, &block)
84
+ @argument_list_matcher = ArgumentListMatcher.new(*args)
85
+ super
86
+ end
87
+
88
+ private
89
+
90
+ def negated?
91
+ messages.any? { |(message, *_), _| message == :never }
92
+ end
93
+
94
+ def messages
95
+ @messages ||= []
96
+ end
97
+
98
+ def last_message
99
+ messages.last.first.first unless messages.empty?
100
+ end
101
+
102
+ def record(rspec_method_name, *args, &block)
103
+ verify_invocation_order(rspec_method_name, *args, &block)
104
+ messages << [args.unshift(rspec_method_name), block]
105
+ self
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,31 @@
1
+ module RSpec
2
+ module Mocks
3
+ module AnyInstance
4
+ # @private
5
+ class ErrorGenerator < ::RSpec::Mocks::ErrorGenerator
6
+ def raise_second_instance_received_message_error(unfulfilled_expectations)
7
+ __raise "Exactly one instance should have received the following " \
8
+ "message(s) but didn't: #{unfulfilled_expectations.sort.join(', ')}"
9
+ end
10
+
11
+ def raise_does_not_implement_error(klass, method_name)
12
+ __raise "#{klass} does not implement ##{method_name}"
13
+ end
14
+
15
+ def raise_message_already_received_by_other_instance_error(method_name, object_inspect, invoked_instance)
16
+ __raise "The message '#{method_name}' was received by #{object_inspect} " \
17
+ "but has already been received by #{invoked_instance}"
18
+ end
19
+
20
+ def raise_not_supported_with_prepend_error(method_name, problem_mod)
21
+ __raise "Using `any_instance` to stub a method (#{method_name}) that has been " \
22
+ "defined on a prepended module (#{problem_mod}) is not supported."
23
+ end
24
+ end
25
+
26
+ def self.error_generator
27
+ @error_generator ||= ErrorGenerator.new
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ module RSpec
2
+ module Mocks
3
+ module AnyInstance
4
+ # @private
5
+ class ExpectChainChain < StubChain
6
+ def initialize(*args)
7
+ super
8
+ @expectation_fulfilled = false
9
+ end
10
+
11
+ def expectation_fulfilled?
12
+ @expectation_fulfilled
13
+ end
14
+
15
+ def playback!(instance)
16
+ super.tap { @expectation_fulfilled = true }
17
+ end
18
+
19
+ private
20
+
21
+ def create_message_expectation_on(instance)
22
+ ::RSpec::Mocks::ExpectChain.expect_chain_on(instance, *@expectation_args, &@expectation_block)
23
+ end
24
+
25
+ def invocation_order
26
+ EmptyInvocationOrder
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module RSpec
2
+ module Mocks
3
+ module AnyInstance
4
+ # @private
5
+ class ExpectationChain < Chain
6
+ def expectation_fulfilled?
7
+ @expectation_fulfilled || constrained_to_any_of?(:never)
8
+ end
9
+
10
+ def initialize(*args, &block)
11
+ @expectation_fulfilled = false
12
+ super
13
+ end
14
+
15
+ private
16
+
17
+ def verify_invocation_order(_rspec_method_name, *_args, &_block)
18
+ end
19
+ end
20
+
21
+ # @private
22
+ class PositiveExpectationChain < ExpectationChain
23
+ private
24
+
25
+ def create_message_expectation_on(instance)
26
+ proxy = ::RSpec::Mocks.space.proxy_for(instance)
27
+ method_name, opts = @expectation_args
28
+ opts = (opts || {}).merge(:expected_form => IGNORED_BACKTRACE_LINE)
29
+
30
+ me = proxy.add_message_expectation(method_name, opts, &@expectation_block)
31
+ if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
32
+ me.and_yield_receiver_to_implementation
33
+ end
34
+
35
+ me
36
+ end
37
+
38
+ ExpectationInvocationOrder =
39
+ {
40
+ :and_return => [:with, nil],
41
+ :and_raise => [:with, nil],
42
+ }.freeze
43
+
44
+ def invocation_order
45
+ ExpectationInvocationOrder
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,83 @@
1
+ module RSpec
2
+ module Mocks
3
+ module AnyInstance
4
+ # @private
5
+ class MessageChains
6
+ def initialize
7
+ @chains_by_method_name = Hash.new { |h, k| h[k] = [] }
8
+ end
9
+
10
+ # @private
11
+ def [](method_name)
12
+ @chains_by_method_name[method_name]
13
+ end
14
+
15
+ # @private
16
+ def add(method_name, chain)
17
+ @chains_by_method_name[method_name] << chain
18
+ chain
19
+ end
20
+
21
+ # @private
22
+ def remove_stub_chains_for!(method_name)
23
+ @chains_by_method_name[method_name].reject! do |chain|
24
+ StubChain === chain
25
+ end
26
+ end
27
+
28
+ # @private
29
+ def has_expectation?(method_name)
30
+ @chains_by_method_name[method_name].find do |chain|
31
+ ExpectationChain === chain
32
+ end
33
+ end
34
+
35
+ # @private
36
+ def each_unfulfilled_expectation_matching(method_name, *args)
37
+ @chains_by_method_name[method_name].each do |chain|
38
+ yield chain if !chain.expectation_fulfilled? && chain.matches_args?(*args)
39
+ end
40
+ end
41
+
42
+ # @private
43
+ def all_expectations_fulfilled?
44
+ @chains_by_method_name.all? do |_method_name, chains|
45
+ chains.all? { |chain| chain.expectation_fulfilled? }
46
+ end
47
+ end
48
+
49
+ # @private
50
+ def unfulfilled_expectations
51
+ @chains_by_method_name.map do |method_name, chains|
52
+ method_name.to_s if ExpectationChain === chains.last unless chains.last.expectation_fulfilled?
53
+ end.compact
54
+ end
55
+
56
+ # @private
57
+ def received_expected_message!(method_name)
58
+ @chains_by_method_name[method_name].each do |chain|
59
+ chain.expectation_fulfilled!
60
+ end
61
+ end
62
+
63
+ # @private
64
+ def playback!(instance, method_name)
65
+ raise_if_second_instance_to_receive_message(instance)
66
+ @chains_by_method_name[method_name].each do |chain|
67
+ chain.playback!(instance)
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def raise_if_second_instance_to_receive_message(instance)
74
+ @instance_with_expectation ||= instance if ExpectationChain === instance
75
+ return unless ExpectationChain === instance
76
+ return if @instance_with_expectation.equal?(instance)
77
+
78
+ AnyInstance.error_generator.raise_second_instance_received_message_error(unfulfilled_expectations)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end