rspec-mocks 2.8.0.rc1 → 2.8.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,11 @@
1
1
  module RSpec
2
2
  module Mocks
3
+ # @private
3
4
  class MethodDouble < Hash
5
+ # @private
4
6
  attr_reader :method_name
5
7
 
8
+ # @private
6
9
  def initialize(object, method_name, proxy)
7
10
  @method_name = method_name
8
11
  @object = object
@@ -12,14 +15,17 @@ module RSpec
12
15
  store(:stubs, [])
13
16
  end
14
17
 
18
+ # @private
15
19
  def expectations
16
20
  self[:expectations]
17
21
  end
18
22
 
23
+ # @private
19
24
  def stubs
20
25
  self[:stubs]
21
26
  end
22
27
 
28
+ # @private
23
29
  def visibility
24
30
  if Mock === @object
25
31
  'public'
@@ -32,18 +38,22 @@ module RSpec
32
38
  end
33
39
  end
34
40
 
41
+ # @private
35
42
  def object_singleton_class
36
43
  class << @object; self; end
37
44
  end
38
45
 
46
+ # @private
39
47
  def obfuscate(method_name)
40
48
  "obfuscated_by_rspec_mocks__#{method_name}"
41
49
  end
42
50
 
51
+ # @private
43
52
  def stashed_method_name
44
53
  obfuscate(method_name)
45
54
  end
46
55
 
56
+ # @private
47
57
  def object_responds_to?(method_name)
48
58
  if @proxy.already_proxied_respond_to?
49
59
  @object.__send__(obfuscate(:respond_to?), method_name)
@@ -54,6 +64,7 @@ module RSpec
54
64
  end
55
65
  end
56
66
 
67
+ # @private
57
68
  def configure_method
58
69
  RSpec::Mocks::space.add(@object) if RSpec::Mocks::space
59
70
  warn_if_nil_class
@@ -63,6 +74,7 @@ module RSpec
63
74
  end
64
75
  end
65
76
 
77
+ # @private
66
78
  def stash_original_method
67
79
  stashed = stashed_method_name
68
80
  orig = @method_name
@@ -72,6 +84,7 @@ module RSpec
72
84
  @stashed = true
73
85
  end
74
86
 
87
+ # @private
75
88
  def define_proxy_method
76
89
  method_name = @method_name
77
90
  visibility_for_method = "#{visibility} :#{method_name}"
@@ -79,10 +92,11 @@ module RSpec
79
92
  def #{method_name}(*args, &block)
80
93
  __mock_proxy.message_received :#{method_name}, *args, &block
81
94
  end
82
- #{visibility_for_method}
95
+ #{visibility_for_method}
83
96
  EOF
84
97
  end
85
98
 
99
+ # @private
86
100
  def restore_original_method
87
101
  if @stashed
88
102
  method_name = @method_name
@@ -98,32 +112,37 @@ module RSpec
98
112
  end
99
113
  end
100
114
 
115
+ # @private
101
116
  def verify
102
117
  expectations.each {|e| e.verify_messages_received}
103
118
  end
104
119
 
120
+ # @private
105
121
  def reset
106
122
  reset_nil_expectations_warning
107
123
  restore_original_method
108
124
  clear
109
125
  end
110
126
 
127
+ # @private
111
128
  def clear
112
129
  expectations.clear
113
130
  stubs.clear
114
131
  end
115
132
 
133
+ # @private
116
134
  def add_expectation(error_generator, expectation_ordering, expected_from, opts, &block)
117
135
  configure_method
118
136
  expectation = if existing_stub = stubs.first
119
- existing_stub.build_child(expected_from, block, 1, opts)
120
- else
121
- MessageExpectation.new(error_generator, expectation_ordering, expected_from, @method_name, block, 1, opts)
122
- end
137
+ existing_stub.build_child(expected_from, block, 1, opts)
138
+ else
139
+ MessageExpectation.new(error_generator, expectation_ordering, expected_from, @method_name, block, 1, opts)
140
+ end
123
141
  expectations << expectation
124
142
  expectation
125
143
  end
126
144
 
145
+ # @private
127
146
  def add_negative_expectation(error_generator, expectation_ordering, expected_from, &implementation)
128
147
  configure_method
129
148
  expectation = NegativeMessageExpectation.new(error_generator, expectation_ordering, expected_from, @method_name, implementation)
@@ -131,32 +150,38 @@ module RSpec
131
150
  expectation
132
151
  end
133
152
 
153
+ # @private
134
154
  def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)
135
155
  configure_method
136
156
  stub = MessageExpectation.new(error_generator, expectation_ordering, expected_from, @method_name, nil, :any, opts, &implementation)
137
157
  stubs.unshift stub
138
158
  stub
139
159
  end
140
-
160
+
161
+ # @private
141
162
  def remove_stub
142
163
  raise_method_not_stubbed_error if stubs.empty?
143
164
  expectations.empty? ? reset : stubs.clear
144
165
  end
145
166
 
167
+ # @private
146
168
  def proxy_for_nil_class?
147
169
  @object.nil?
148
170
  end
149
171
 
172
+ # @private
150
173
  def warn_if_nil_class
151
174
  if proxy_for_nil_class? & RSpec::Mocks::Proxy.warn_about_expectations_on_nil
152
175
  Kernel.warn("An expectation of :#{@method_name} was set on nil. Called from #{caller[4]}. Use allow_message_expectations_on_nil to disable warnings.")
153
176
  end
154
177
  end
155
-
178
+
179
+ # @private
156
180
  def raise_method_not_stubbed_error
157
181
  raise MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
158
182
  end
159
183
 
184
+ # @private
160
185
  def reset_nil_expectations_warning
161
186
  RSpec::Mocks::Proxy.warn_about_expectations_on_nil = true if proxy_for_nil_class?
162
187
  end
@@ -1,37 +1,82 @@
1
1
  module RSpec
2
2
  module Mocks
3
+ # Methods that are added to every object.
3
4
  module Methods
4
- def should_receive(sym, opts={}, &block)
5
- __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], sym.to_sym, opts, &block)
5
+ # Sets and expectation that this object should receive a message before
6
+ # the end of the example.
7
+ #
8
+ # @example
9
+ #
10
+ # logger = double('logger')
11
+ # thing_that_logs = ThingThatLogs.new(logger)
12
+ # logger.should_receive(:log)
13
+ # thing_that_logs.do_something_that_logs_a_message
14
+ def should_receive(message, opts={}, &block)
15
+ __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], message.to_sym, opts, &block)
6
16
  end
7
17
 
8
- def should_not_receive(sym, &block)
9
- __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block)
18
+ # Sets and expectation that this object should _not_ receive a message
19
+ # during this example.
20
+ def should_not_receive(message, &block)
21
+ __mock_proxy.add_negative_message_expectation(caller(1)[0], message.to_sym, &block)
10
22
  end
11
-
12
- def stub(sym_or_hash, opts={}, &block)
13
- if Hash === sym_or_hash
14
- sym_or_hash.each {|method, value| stub(method).and_return value }
23
+
24
+ # Tells the object to respond to the message with the specified value.
25
+ #
26
+ # @example
27
+ #
28
+ # counter.stub(:count).and_return(37)
29
+ # counter.stub(:count => 37)
30
+ # counter.stub(:count) { 37 }
31
+ def stub(message_or_hash, opts={}, &block)
32
+ if Hash === message_or_hash
33
+ message_or_hash.each {|message, value| stub(message).and_return value }
15
34
  else
16
- __mock_proxy.add_stub(caller(1)[0], sym_or_hash.to_sym, opts, &block)
35
+ __mock_proxy.add_stub(caller(1)[0], message_or_hash.to_sym, opts, &block)
17
36
  end
18
37
  end
19
-
20
- def unstub(sym)
21
- __mock_proxy.remove_stub(sym)
38
+
39
+ # Removes a stub. On a double, the object will no longer respond to
40
+ # `message`. On a real object, the original method (if it exists) is
41
+ # restored.
42
+ #
43
+ # This is rarely used, but can be useful when a stub is set up during a
44
+ # shared `before` hook for the common case, but you want to replace it
45
+ # for a special case.
46
+ def unstub(message)
47
+ __mock_proxy.remove_stub(message)
22
48
  end
23
-
49
+
24
50
  alias_method :stub!, :stub
25
51
  alias_method :unstub!, :unstub
26
-
27
- # Stubs a chain of methods. Especially useful with fluent and/or
28
- # composable interfaces.
52
+
53
+ # @overload stub_chain(method1, method2)
54
+ # @overload stub_chain("method1.method2")
55
+ # @overload stub_chain(method1, method_to_value_hash)
56
+ #
57
+ # Stubs a chain of methods.
58
+ #
59
+ # ## Warning:
60
+ #
61
+ # Chains can be arbitrarily long, which makes it quite painless to
62
+ # violate the Law of Demeter in violent ways, so you should consider any
63
+ # use of `stub_chain` a code smell. Even though not all code smells
64
+ # indicate real problems (think fluent interfaces), `stub_chain` still
65
+ # results in brittle examples. For example, if you write
66
+ # `foo.stub_chain(:bar, :baz => 37)` in a spec and then the
67
+ # implementation calls `foo.baz.bar`, the stub will not work.
29
68
  #
30
- # == Examples
69
+ # @example
31
70
  #
32
- # double.stub_chain("foo.bar") { :baz }
33
- # double.stub_chain(:foo, :bar) { :baz }
34
- # Article.stub_chain("recent.published") { [Article.new] }
71
+ # double.stub_chain("foo.bar") { :baz }
72
+ # double.stub_chain(:foo, :bar => :baz)
73
+ # double.stub_chain(:foo, :bar) { :baz }
74
+ #
75
+ # # Given any of ^^ these three forms ^^:
76
+ # double.foo.bar # => :baz
77
+ #
78
+ # # Common use in Rails/ActiveRecord:
79
+ # Article.stub_chain("recent.published") { [Article.new] }
35
80
  def stub_chain(*chain, &blk)
36
81
  chain, blk = format_chain(*chain, &blk)
37
82
  if chain.length > 1
@@ -47,26 +92,33 @@ module RSpec
47
92
  stub(chain.shift, &blk)
48
93
  end
49
94
  end
50
-
95
+
96
+ # Tells the object to respond to all messages. If specific stub values
97
+ # are declared, they'll work as expected. If not, the receiver is
98
+ # returned.
99
+ def as_null_object
100
+ __mock_proxy.as_null_object
101
+ end
102
+
103
+ # Returns true if this object has received `as_null_object`
104
+ def null_object?
105
+ __mock_proxy.null_object?
106
+ end
107
+
108
+ # @private
51
109
  def received_message?(sym, *args, &block)
52
110
  __mock_proxy.received_message?(sym.to_sym, *args, &block)
53
111
  end
54
-
112
+
113
+ # @private
55
114
  def rspec_verify
56
115
  __mock_proxy.verify
57
116
  end
58
117
 
118
+ # @private
59
119
  def rspec_reset
60
120
  __mock_proxy.reset
61
121
  end
62
-
63
- def as_null_object
64
- __mock_proxy.as_null_object
65
- end
66
-
67
- def null_object?
68
- __mock_proxy.null_object?
69
- end
70
122
 
71
123
  private
72
124
 
@@ -3,8 +3,8 @@ module RSpec
3
3
  class Mock
4
4
  include Methods
5
5
 
6
- # Creates a new test double with a +name+ (that will be used in error messages
7
- # only)
6
+ # Creates a new test double with a `name` (that will be used in error
7
+ # messages only)
8
8
  def initialize(name=nil, stubs_and_options={})
9
9
  if name.is_a?(Hash) && stubs_and_options.empty?
10
10
  stubs_and_options = name
@@ -24,18 +24,21 @@ module RSpec
24
24
  other == __mock_proxy
25
25
  end
26
26
 
27
+ # @private
27
28
  def inspect
28
29
  "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>"
29
30
  end
30
31
 
32
+ # @private
31
33
  def to_s
32
34
  inspect.gsub('<','[').gsub('>',']')
33
35
  end
34
36
 
35
37
  alias_method :to_str, :to_s
36
38
 
39
+ # @private
37
40
  def respond_to?(sym, incl_private=false)
38
- __mock_proxy.null_object? && sym != :to_ary ? true : super
41
+ __mock_proxy.null_object? && sym != :to_ary ? true : super
39
42
  end
40
43
 
41
44
  private
@@ -59,7 +62,7 @@ module RSpec
59
62
  extract_option(stubs_and_options, options, :__declared_as, 'Mock')
60
63
  options
61
64
  end
62
-
65
+
63
66
  def extract_option(source, target, key, default=nil)
64
67
  if source[key]
65
68
  target[key] = source.delete(key)
@@ -76,4 +79,3 @@ module RSpec
76
79
  end
77
80
  end
78
81
  end
79
-
@@ -1,29 +1,33 @@
1
1
  module RSpec
2
2
  module Mocks
3
+ # @private
3
4
  class OrderGroup
4
5
  def initialize error_generator
5
6
  @error_generator = error_generator
6
7
  @ordering = Array.new
7
8
  end
8
-
9
+
10
+ # @private
9
11
  def register(expectation)
10
12
  @ordering << expectation
11
13
  end
12
-
14
+
15
+ # @private
13
16
  def ready_for?(expectation)
14
17
  return @ordering.first == expectation
15
18
  end
16
-
19
+
20
+ # @private
17
21
  def consume
18
22
  @ordering.shift
19
23
  end
20
-
24
+
25
+ # @private
21
26
  def handle_order_constraint expectation
22
27
  return unless @ordering.include? expectation
23
28
  return consume if ready_for?(expectation)
24
29
  @error_generator.raise_out_of_order_error expectation.sym
25
30
  end
26
-
27
31
  end
28
32
  end
29
33
  end
@@ -1,43 +1,51 @@
1
1
  module RSpec
2
2
  module Mocks
3
+ # @private
3
4
  class Proxy
4
5
  class << self
6
+ # @private
5
7
  def warn_about_expectations_on_nil
6
8
  defined?(@warn_about_expectations_on_nil) ? @warn_about_expectations_on_nil : true
7
9
  end
8
-
10
+
11
+ # @private
9
12
  def warn_about_expectations_on_nil=(new_value)
10
13
  @warn_about_expectations_on_nil = new_value
11
14
  end
12
-
15
+
16
+ # @private
13
17
  def allow_message_expectations_on_nil
14
18
  @warn_about_expectations_on_nil = false
15
-
19
+
16
20
  # ensure nil.rspec_verify is called even if an expectation is not set in the example
17
21
  # otherwise the allowance would effect subsequent examples
18
22
  RSpec::Mocks::space.add(nil) unless RSpec::Mocks::space.nil?
19
23
  end
20
24
 
25
+ # @private
21
26
  def allow_message_expectations_on_nil?
22
27
  !warn_about_expectations_on_nil
23
28
  end
24
29
  end
25
30
 
31
+ # @private
26
32
  def initialize(object, name=nil, options={})
27
33
  @object = object
28
34
  @name = name
29
35
  @error_generator = ErrorGenerator.new object, name, options
30
36
  @expectation_ordering = OrderGroup.new @error_generator
31
- @messages_received = []
37
+ @messages_received = []
32
38
  @options = options
33
39
  @already_proxied_respond_to = false
34
40
  @null_object = false
35
41
  end
36
42
 
43
+ # @private
37
44
  def null_object?
38
45
  @null_object
39
46
  end
40
47
 
48
+ # @private
41
49
  # Tells the object to ignore any messages that aren't explicitly set as
42
50
  # stubs or message expectations.
43
51
  def as_null_object
@@ -45,52 +53,64 @@ module RSpec
45
53
  @object
46
54
  end
47
55
 
56
+ # @private
48
57
  def already_proxied_respond_to
49
58
  @already_proxied_respond_to = true
50
59
  end
51
60
 
61
+ # @private
52
62
  def already_proxied_respond_to?
53
63
  @already_proxied_respond_to
54
64
  end
55
65
 
66
+ # @private
56
67
  def add_message_expectation(location, method_name, opts={}, &block)
57
68
  method_double[method_name].add_expectation @error_generator, @expectation_ordering, location, opts, &block
58
69
  end
59
70
 
71
+ # @private
60
72
  def add_negative_message_expectation(location, method_name, &implementation)
61
73
  method_double[method_name].add_negative_expectation @error_generator, @expectation_ordering, location, &implementation
62
74
  end
63
75
 
76
+ # @private
64
77
  def add_stub(location, method_name, opts={}, &implementation)
65
78
  method_double[method_name].add_stub @error_generator, @expectation_ordering, location, opts, &implementation
66
79
  end
67
-
80
+
81
+ # @private
68
82
  def remove_stub(method_name)
69
83
  method_double[method_name].remove_stub
70
84
  end
71
-
85
+
86
+ # @private
72
87
  def verify
73
88
  method_doubles.each {|d| d.verify}
74
89
  ensure
75
90
  reset
76
91
  end
77
92
 
93
+ # @private
78
94
  def reset
79
95
  method_doubles.each {|d| d.reset}
80
96
  end
81
97
 
98
+ # @private
82
99
  def received_message?(method_name, *args, &block)
83
100
  @messages_received.any? {|array| array == [method_name, args, block]}
84
101
  end
85
102
 
103
+ # @private
86
104
  def has_negative_expectation?(method_name)
87
105
  method_double[method_name].expectations.detect {|expectation| expectation.negative_expectation_for?(method_name)}
88
106
  end
89
-
107
+
108
+ # @private
90
109
  def record_message_received(method_name, *args, &block)
91
110
  @messages_received << [method_name, args, block]
92
111
  end
93
112
 
113
+ # @private
94
114
  def message_received(method_name, *args, &block)
95
115
  expectation = find_matching_expectation(method_name, *args)
96
116
  stub = find_matching_method_stub(method_name, *args)
@@ -116,15 +136,17 @@ module RSpec
116
136
  end
117
137
  end
118
138
 
139
+ # @private
119
140
  def raise_unexpected_message_args_error(expectation, *args)
120
141
  @error_generator.raise_unexpected_message_args_error(expectation, *args)
121
142
  end
122
143
 
144
+ # @private
123
145
  def raise_unexpected_message_error(method_name, *args)
124
146
  @error_generator.raise_unexpected_message_error method_name, *args
125
147
  end
126
-
127
- private
148
+
149
+ private
128
150
 
129
151
  def method_double
130
152
  @method_double ||= Hash.new {|h,k|
@@ -135,10 +157,10 @@ module RSpec
135
157
  def method_doubles
136
158
  method_double.values
137
159
  end
138
-
160
+
139
161
  def find_matching_expectation(method_name, *args)
140
162
  method_double[method_name].expectations.find {|expectation| expectation.matches?(method_name, *args) && !expectation.called_max_times?} ||
141
- method_double[method_name].expectations.find {|expectation| expectation.matches?(method_name, *args)}
163
+ method_double[method_name].expectations.find {|expectation| expectation.matches?(method_name, *args)}
142
164
  end
143
165
 
144
166
  def find_almost_matching_expectation(method_name, *args)
@@ -152,7 +174,6 @@ module RSpec
152
174
  def find_almost_matching_stub(method_name, *args)
153
175
  method_double[method_name].stubs.find {|stub| stub.matches_name_but_not_args(method_name, *args)}
154
176
  end
155
-
156
177
  end
157
178
  end
158
179
  end