rspec-mocks 3.1.3 → 3.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8967bb910d6e9e42450e14ac9ce3fd37b078ba5e
4
- data.tar.gz: e05cfe6e3b29c252f091de7f562e3b2424a14a1c
3
+ metadata.gz: 23676d8c392cc0e21a6fc7fdec5248f084775150
4
+ data.tar.gz: fbaf8723ad0840c4da3dc8c6cc21093d2bd2f1c7
5
5
  SHA512:
6
- metadata.gz: 72a62c1548028c0517d412fdd5b62bd8047135a6a25696f180df864b9cc4e0332be07f29290888fe1375afa7de822e404f36d6111e83ab739dee57cbf5676c17
7
- data.tar.gz: 496c5678781c6c5f14a3d929521f3e57698a28bf25766efd67eb5d918f93c108467228636275fbedbf71a34b56d28acb001ce47a6bd215cf74bb28e465b28b39
6
+ metadata.gz: 2563565823fee6d8c5f0a3358af1fb0ed0a12d77f1128c82bcae6d3583cfdd7206d59dfbf2d0213d10ce10c5a480b31317b92194586c0ce7e1fb800e4e8b95c5
7
+ data.tar.gz: 00664f4764abbf01ab4c93986454c1d7582abba0fefc378f5abf1a4908fc2e66028242565843377b53e4f58310937d8c7c4747a2b961c9009e36774be83a4e62
Binary file
data.tar.gz.sig CHANGED
@@ -1,3 +1,5 @@
1
- �V��F��W��S��
2
- r65Vr�����m}�[��?�j5w��b�<:n��1�Ҝl9K(%p��6��wx��-Z����ڃm��������D�L����t7a����6I��~�>��p%]` �ՅN����앻��rz��q��w�㟢Ra�hؑj
3
- "E� DL��v�g�G.QR�Óc�nJ�,��j{4�)�qNJ+�)Dg�N�2���&%��w�ׯ��#a
1
+ *�$���W��_��Y�&Q�H$$Y"p+@�΢@�ڟ�TO�@��.7ીu�[�d�}�)�5˸p���\��p������B�f�j��w��K�|�)�K{bC�
2
+ b��hl?Ս�)qx���ٮ�eXIY�ё�ء"o��E��P������<�U}�yf�罣� ��[�ܲx
3
+ Mcl�|��
4
+ �ި�7�=63[?�����;�[\���x�Jɸn@� �@�ʎ���x�*�=O��h�;�%��Ya^R�M/��n�*o�W�$Ze�dR�%�=
5
+ �������#��y� �����1ʔ��t�"�2� *(C������8+�r�=�M
@@ -1,3 +1,59 @@
1
+ ### 3.2.0 / 2015-02-03
2
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.3...v3.2.0)
3
+
4
+ Enhancements:
5
+
6
+ * Treat `any_args` as an arg splat, allowing it to match an arbitrary
7
+ number of args at any point in an arg list. (Myron Marston, #786)
8
+ * Print diffs when arguments in mock expectations are mismatched.
9
+ (Sam Phippen, #751)
10
+ * Support names for verified doubles (`instance_double`, `instance_spy`,
11
+ `class_double`, `class_spy`, `object_double`, `object_spy`). (Cezary
12
+ Baginski, #826)
13
+ * Make `array_including` and `hash_including` argument matchers composable.
14
+ (Sam Phippen, #819)
15
+ * Make `allow_any_instance_of(...).to receive(...).and_wrap_original`
16
+ work. (Ryan Fitzgerald, #869)
17
+
18
+ Bug Fixes:
19
+
20
+ * Provide a clear error when users wrongly combine `no_args` with
21
+ additional arguments (e.g. `expect().to receive().with(no_args, 1)`).
22
+ (Myron Marston, #786)
23
+ * Provide a clear error when users wrongly use `any_args` multiple times in the
24
+ same argument list (e.g. `expect().to receive().with(any_args, 1, any_args)`.
25
+ (Myron Marston, #786)
26
+ * Prevent the error generator from using user object #description methods.
27
+ See [#685](https://github.com/rspec/rspec-mocks/issues/685).
28
+ (Sam Phippen, #751)
29
+ * Make verified doubles declared as `(instance|class)_double(SomeConst)`
30
+ work properly when `SomeConst` has previously been stubbed.
31
+ `(instance|class)_double("SomeClass")` already worked properly.
32
+ (Myron Marston, #824)
33
+ * Add a matcher description for `receive`, `receive_messages` and
34
+ `receive_message_chain`. (Myron Marston, #828)
35
+ * Validate invocation args for null object verified doubles.
36
+ (Myron Marston, #829)
37
+ * Fix `RSpec::Mocks::Constant.original` when called with an invalid
38
+ constant to return an object indicating the constant name is invalid,
39
+ rather than blowing up. (Myron Marston, #833)
40
+ * Make `extend RSpec::Mocks::ExampleMethods` on any object work properly
41
+ to add the rspec-mocks API to that object. Previously, `expect` would
42
+ be undefined. (Myron Marston, #846)
43
+ * Fix `require 'rspec/mocks/standalone'` so that it only affects `main`
44
+ and not every object. It's really only intended to be used in a REPL
45
+ like IRB, but some gems have loaded it, thinking it needs to be loaded
46
+ when using rspec-mocks outside the context of rspec-core.
47
+ (Myron Marston, #846)
48
+ * Prevent message expectations from being modified by customization methods
49
+ (e.g. `with`) after they have been invoked. (Sam Phippen and Melanie Gilman, #837)
50
+ * Handle cases where a method stub cannot be removed due to something
51
+ external to RSpec monkeying with the method definition. This can
52
+ happen, for example, when you `file.reopen(io)` after previously
53
+ stubbing a method on the `file` object. (Myron Marston, #853)
54
+ * Provide a clear error when received message args are mutated before
55
+ a `have_received(...).with(...)` expectation. (Myron Marston, #868)
56
+
1
57
  ### 3.1.3 / 2014-10-08
2
58
  [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.1.2...v3.1.3)
3
59
 
@@ -48,7 +104,7 @@ Enhancements:
48
104
  * Add `and_wrap_original` modifier for partial doubles to mutate the
49
105
  response from a method. (Jon Rowe, #762)
50
106
 
51
- Bugfixes:
107
+ Bug Fixes:
52
108
 
53
109
  * Remove `any_number_of_times` from `any_instance` recorders that were
54
110
  erroneously causing mention of the method in documentation. (Jon Rowe, #760)
@@ -240,7 +296,7 @@ Bug Fixes:
240
296
  behavior. (Maurício Linhares)
241
297
 
242
298
  ### 3.0.0.beta1 / 2013-11-07
243
- [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.2...v3.0.0.beta1)
299
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.3...v3.0.0.beta1)
244
300
 
245
301
  Breaking Changes for 3.0.0:
246
302
 
@@ -303,6 +359,13 @@ Bug Fixes:
303
359
  returns `nil` or `''` so that you still get a useful message.
304
360
  (Nick DeLuca)
305
361
 
362
+ ### 2.99.3 / 2015-01-09
363
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.2...v2.99.3)
364
+
365
+ Bug Fixes:
366
+
367
+ * Fix regression that caused an error when a test double was deserialized from YAML. (Yuji Nakayama, #777)
368
+
306
369
  ### 2.99.2 / 2014-07-21
307
370
  [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.99.1...v2.99.2)
308
371
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RSpec Mocks [![Build Status](https://secure.travis-ci.org/rspec/rspec-mocks.png?branch=master)](http://travis-ci.org/rspec/rspec-mocks) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.png)](https://codeclimate.com/github/rspec/rspec-mocks)
1
+ # RSpec Mocks [![Build Status](https://secure.travis-ci.org/rspec/rspec-mocks.svg?branch=master)](http://travis-ci.org/rspec/rspec-mocks) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.svg)](https://codeclimate.com/github/rspec/rspec-mocks)
2
2
  rspec-mocks is a test-double framework for rspec with support for method stubs,
3
3
  fakes, and message expectations on generated test-doubles and real objects
4
4
  alike.
@@ -8,6 +8,15 @@ alike.
8
8
  gem install rspec # for rspec-core, rspec-expectations, rspec-mocks
9
9
  gem install rspec-mocks # for rspec-mocks only
10
10
 
11
+ Want to run against the `master` branch? You'll need to include the dependent
12
+ RSpec repos as well. Add the following to your `Gemfile`:
13
+
14
+ ```ruby
15
+ %w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
16
+ gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master'
17
+ end
18
+ ```
19
+
11
20
  ## Test Doubles
12
21
 
13
22
  A test double is an object that stands in for another object in your system
@@ -32,6 +41,16 @@ isolation without your dependencies loaded while still being able to validate
32
41
  them against real objects. More detail is available in [their
33
42
  documentation](https://github.com/rspec/rspec-mocks/blob/master/features/verifying_doubles).
34
43
 
44
+ Verifying doubles can also accept custom identifiers, just like double(), e.g.:
45
+
46
+ ```ruby
47
+ books = []
48
+ books << instance_double("Book", :rspec_book, :pages => 250)
49
+ books << instance_double("Book", "(Untitled)", :pages => 5000)
50
+
51
+ puts books.inspect # with names, it's clearer which were actually added
52
+ ```
53
+
35
54
  ## Method Stubs
36
55
 
37
56
  A method stub is an implementation that returns a pre-determined value. Method
@@ -42,7 +61,7 @@ rspec-mocks supports 3 forms for declaring method stubs:
42
61
  allow(book).to receive(:title) { "The RSpec Book" }
43
62
  allow(book).to receive(:title).and_return("The RSpec Book")
44
63
  allow(book).to receive_messages(
45
- :title => "The RSpec Book",
64
+ :title => "The RSpec Book",
46
65
  :subtitle => "Behaviour-Driven Development with RSpec, Cucumber, and Friends")
47
66
  ```
48
67
 
@@ -206,8 +225,9 @@ rspec-mocks also adds some keyword Symbols that you can use to
206
225
  specify certain kinds of arguments:
207
226
 
208
227
  ```ruby
209
- expect(double).to receive(:msg).with(no_args())
210
- expect(double).to receive(:msg).with(any_args())
228
+ expect(double).to receive(:msg).with(no_args)
229
+ expect(double).to receive(:msg).with(any_args)
230
+ expect(double).to receive(:msg).with(1, any_args) # any args acts like an arg splat and can go anywhere
211
231
  expect(double).to receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can be any kind of Numeric
212
232
  expect(double).to receive(:msg).with(1, boolean(), "b") #2nd argument can be true or false
213
233
  expect(double).to receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
@@ -366,7 +386,7 @@ general we discourage its use for a number of reasons:
366
386
 
367
387
  * The `rspec-mocks` API is designed for individual object instances, but this
368
388
  feature operates on entire classes of objects. As a result there are some
369
- sematically confusing edge cases. For example in
389
+ semantically confusing edge cases. For example in
370
390
  `expect_any_instance_of(Widget).to receive(:name).twice` it isn't clear
371
391
  whether each specific instance is expected to receive `name` twice, or if two
372
392
  receives total are expected. (It's the former.)
@@ -34,6 +34,7 @@ module RSpec
34
34
  record :and_throw
35
35
  record :and_yield
36
36
  record :and_call_original
37
+ record :and_wrap_original
37
38
  record :with
38
39
  record :once
39
40
  record :twice
@@ -31,7 +31,8 @@ module RSpec
31
31
  :and_return => [:with, nil],
32
32
  :and_raise => [:with, nil],
33
33
  :and_yield => [:with, nil],
34
- :and_call_original => [:with, nil]
34
+ :and_call_original => [:with, nil],
35
+ :and_wrap_original => [:with, nil]
35
36
  }
36
37
  end
37
38
 
@@ -44,12 +44,7 @@ module RSpec
44
44
  # @see #args_match?
45
45
  def initialize(*expected_args)
46
46
  @expected_args = expected_args
47
-
48
- @matchers = case expected_args.first
49
- when ArgumentMatchers::AnyArgsMatcher then Array
50
- when ArgumentMatchers::NoArgsMatcher then []
51
- else expected_args
52
- end
47
+ ensure_expected_args_valid!
53
48
  end
54
49
 
55
50
  # @api public
@@ -60,13 +55,46 @@ module RSpec
60
55
  #
61
56
  # @see #initialize
62
57
  def args_match?(*args)
63
- Support::FuzzyMatcher.values_match?(@matchers, args)
58
+ Support::FuzzyMatcher.values_match?(resolve_expected_args_based_on(args), args)
59
+ end
60
+
61
+ # @private
62
+ # Resolves abstract arg placeholders like `no_args` and `any_args` into
63
+ # a more concrete arg list based on the provided `actual_args`.
64
+ def resolve_expected_args_based_on(actual_args)
65
+ return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] == expected_args
66
+
67
+ any_args_index = expected_args.index(ArgumentMatchers::AnyArgsMatcher::INSTANCE)
68
+ return expected_args unless any_args_index
69
+
70
+ replace_any_args_with_splat_of_anything(any_args_index, actual_args.count)
71
+ end
72
+
73
+ private
74
+
75
+ def replace_any_args_with_splat_of_anything(before_count, actual_args_count)
76
+ any_args_count = actual_args_count - expected_args.count + 1
77
+ after_count = expected_args.count - before_count - 1
78
+
79
+ any_args = 1.upto(any_args_count).map { ArgumentMatchers::AnyArgMatcher::INSTANCE }
80
+ expected_args.first(before_count) + any_args + expected_args.last(after_count)
81
+ end
82
+
83
+ def ensure_expected_args_valid!
84
+ if expected_args.count(ArgumentMatchers::AnyArgsMatcher::INSTANCE) > 1
85
+ raise ArgumentError, "`any_args` can only be passed to " \
86
+ "`with` once but you have passed it multiple times."
87
+ elsif expected_args.count > 1 && expected_args.include?(ArgumentMatchers::NoArgsMatcher::INSTANCE)
88
+ raise ArgumentError, "`no_args` can only be passed as a " \
89
+ "singleton argument to `with` (i.e. `with(no_args)`), " \
90
+ "but you have passed additional arguments."
91
+ end
64
92
  end
65
93
 
66
94
  # Value that will match all argument lists.
67
95
  #
68
96
  # @private
69
- MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher.new)
97
+ MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher::INSTANCE)
70
98
  end
71
99
  end
72
100
  end
@@ -14,14 +14,18 @@ module RSpec
14
14
  #
15
15
  # @see ArgumentListMatcher
16
16
  module ArgumentMatchers
17
- # Matches any args at all. Supports a more explicit variation of
18
- # `expect(object).to receive(:message)`
17
+ # Acts like an arg splat, matching any number of args at any point in an arg list.
19
18
  #
20
19
  # @example
21
20
  #
22
- # expect(object).to receive(:message).with(any_args)
21
+ # expect(object).to receive(:message).with(1, 2, any_args)
22
+ #
23
+ # # matches any of these:
24
+ # object.message(1, 2)
25
+ # object.message(1, 2, 3)
26
+ # object.message(1, 2, 3, 4)
23
27
  def any_args
24
- AnyArgsMatcher.new
28
+ AnyArgsMatcher::INSTANCE
25
29
  end
26
30
 
27
31
  # Matches any argument at all.
@@ -30,7 +34,7 @@ module RSpec
30
34
  #
31
35
  # expect(object).to receive(:message).with(anything)
32
36
  def anything
33
- AnyArgMatcher.new
37
+ AnyArgMatcher::INSTANCE
34
38
  end
35
39
 
36
40
  # Matches no arguments.
@@ -39,7 +43,7 @@ module RSpec
39
43
  #
40
44
  # expect(object).to receive(:message).with(no_args)
41
45
  def no_args
42
- NoArgsMatcher.new
46
+ NoArgsMatcher::INSTANCE
43
47
  end
44
48
 
45
49
  # Matches if the actual argument responds to the specified messages.
@@ -58,7 +62,7 @@ module RSpec
58
62
  #
59
63
  # expect(object).to receive(:message).with(boolean())
60
64
  def boolean
61
- BooleanMatcher.new
65
+ BooleanMatcher::INSTANCE
62
66
  end
63
67
 
64
68
  # Matches a hash that includes the specified key(s) or key/value pairs.
@@ -122,19 +126,36 @@ module RSpec
122
126
  # @private
123
127
  def self.anythingize_lonely_keys(*args)
124
128
  hash = args.last.class == Hash ? args.delete_at(-1) : {}
125
- args.each { | arg | hash[arg] = AnyArgMatcher.new }
129
+ args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE }
126
130
  hash
127
131
  end
128
132
 
133
+ # Intended to be subclassed by stateless, immutable argument matchers.
134
+ # Provides a `<klass name>::INSTANCE` constant for accessing a global
135
+ # singleton instance of the matcher. There is no need to construct
136
+ # multiple instance since there is no state. It also facilities the
137
+ # special case logic we need for some of these matchers, by making it
138
+ # easy to do comparisons like: `[klass::INSTANCE] == args` rather than
139
+ # `args.count == 1 && klass === args.first`.
140
+ #
141
+ # @private
142
+ class SingletonMatcher
143
+ private_class_method :new
144
+
145
+ def self.inherited(subklass)
146
+ subklass.const_set(:INSTANCE, subklass.send(:new))
147
+ end
148
+ end
149
+
129
150
  # @private
130
- class AnyArgsMatcher
151
+ class AnyArgsMatcher < SingletonMatcher
131
152
  def description
132
- "any args"
153
+ "*(any args)"
133
154
  end
134
155
  end
135
156
 
136
157
  # @private
137
- class AnyArgMatcher
158
+ class AnyArgMatcher < SingletonMatcher
138
159
  def ===(_other)
139
160
  true
140
161
  end
@@ -145,14 +166,14 @@ module RSpec
145
166
  end
146
167
 
147
168
  # @private
148
- class NoArgsMatcher
169
+ class NoArgsMatcher < SingletonMatcher
149
170
  def description
150
171
  "no args"
151
172
  end
152
173
  end
153
174
 
154
175
  # @private
155
- class BooleanMatcher
176
+ class BooleanMatcher < SingletonMatcher
156
177
  def ===(value)
157
178
  true == value || false == value
158
179
  end
@@ -177,7 +198,20 @@ module RSpec
177
198
  end
178
199
 
179
200
  def description(name)
180
- "#{name}(#{@expected.inspect.sub(/^\{/, "").sub(/\}$/, "")})"
201
+ "#{name}(#{formatted_expected_hash.inspect.sub(/^\{/, "").sub(/\}$/, "")})"
202
+ end
203
+
204
+ private
205
+
206
+ def formatted_expected_hash
207
+ Hash[
208
+ @expected.map do |k, v|
209
+ k = RSpec::Support.rspec_description_for_object(k)
210
+ v = RSpec::Support.rspec_description_for_object(v)
211
+
212
+ [k, v]
213
+ end
214
+ ]
181
215
  end
182
216
  end
183
217
 
@@ -210,11 +244,24 @@ module RSpec
210
244
  end
211
245
 
212
246
  def ===(actual)
213
- Set.new(actual).superset?(Set.new(@expected))
247
+ actual = actual.uniq
248
+ @expected.uniq.all? do |expected_element|
249
+ actual.any? do |actual_element|
250
+ RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element)
251
+ end
252
+ end
214
253
  end
215
254
 
216
255
  def description
217
- "array_including(#{@expected.join(", ")})"
256
+ "array_including(#{formatted_expected_values})"
257
+ end
258
+
259
+ private
260
+
261
+ def formatted_expected_values
262
+ @expected.map do |x|
263
+ RSpec::Support.rspec_description_for_object(x)
264
+ end.join(", ")
218
265
  end
219
266
  end
220
267
 
@@ -104,6 +104,23 @@ module RSpec
104
104
  # isolated unit test will prevent you from being able to isolate it!
105
105
  attr_writer :verify_doubled_constant_names
106
106
 
107
+ # Provides a way to perform customisations when verifying doubles.
108
+ #
109
+ # @example
110
+ #
111
+ # RSpec::Mocks.configuration.when_declaring_verifying_double do |ref|
112
+ # ref.some_method!
113
+ # end
114
+ def when_declaring_verifying_double(&block)
115
+ verifying_double_declaration_callbacks << block
116
+ end
117
+
118
+ # @api private
119
+ # Returns an array of blocks to call when verifying doubles
120
+ def verifying_double_declaration_callbacks
121
+ @verifying_double_declaration_callbacks ||= []
122
+ end
123
+
107
124
  def transfer_nested_constants?
108
125
  !!@transfer_nested_constants
109
126
  end
@@ -123,6 +140,24 @@ module RSpec
123
140
  @verify_partial_doubles
124
141
  end
125
142
 
143
+ if ::RSpec.respond_to?(:configuration)
144
+ def color?
145
+ ::RSpec.configuration.color_enabled?
146
+ end
147
+ else
148
+ # Indicates whether or not diffs should be colored.
149
+ # Delegates to rspec-core's color option if rspec-core
150
+ # is loaded; otherwise you can set it here.
151
+ attr_writer :color
152
+
153
+ # Indicates whether or not diffs should be colored.
154
+ # Delegates to rspec-core's color option if rspec-core
155
+ # is loaded; otherwise you can set it here.
156
+ def color?
157
+ @color
158
+ end
159
+ end
160
+
126
161
  # Monkey-patch `Marshal.dump` to enable dumping of mocked or stubbed
127
162
  # objects. By default this will not work since RSpec mocks works by
128
163
  # adding singleton methods that cannot be serialized. This patch removes