rspec-mocks 2.11.1 → 2.11.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,15 @@
1
+ ### 2.11.2 / 2012-08-11
2
+ [full changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.1...v2.11.2)
3
+
4
+ Bug fixes
5
+
6
+ * Don't modify `dup` on classes that don't support `dup` (David Chelimsky)
7
+ * Fix `any_instance` so that it works properly with methods defined on
8
+ a superclass. (Daniel Eguzkiza)
9
+ * Fix `stub_const` so that it works properly for nested constants that
10
+ share a name with a top-level constant (e.g. "MyGem::Hash"). (Myron
11
+ Marston)
12
+
1
13
  ### 2.11.1 / 2012-07-09
2
14
  [full changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.0...v2.11.1)
3
15
 
@@ -13,7 +25,7 @@ Bug fixes
13
25
 
14
26
  Enhancements
15
27
 
16
- * expose ArgumentListMatcher as a formal API
28
+ * Expose ArgumentListMatcher as a formal API
17
29
  * supports use by 3rd party mock frameworks like Surrogate
18
30
  * Add `stub_const` API to stub constants for the duration of an
19
31
  example (Myron Marston).
data/README.md CHANGED
@@ -152,8 +152,8 @@ specify certain kinds of arguments:
152
152
  ```ruby
153
153
  double.should_receive(:msg).with(no_args())
154
154
  double.should_receive(:msg).with(any_args())
155
- double.should_receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can any kind of Numeric
156
- double.should_receive(:msg).with(1, boolean(), "b") #2nd argument can true or false
155
+ double.should_receive(:msg).with(1, kind_of(Numeric), "b") #2nd argument can be any kind of Numeric
156
+ double.should_receive(:msg).with(1, boolean(), "b") #2nd argument can be true or false
157
157
  double.should_receive(:msg).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp
158
158
  double.should_receive(:msg).with(1, anything(), "b") #2nd argument can be anything at all
159
159
  double.should_receive(:msg).with(1, duck_type(:abs, :div), "b")
@@ -4,20 +4,20 @@ Argument matchers can be used:
4
4
 
5
5
  * In stubs to constrain the scope of the stubbed method
6
6
 
7
- obj.stub(:foo).with(:bar) do |arg|
8
- #do something for :bar
9
- end
10
- obj.stub(:foo).with(:baz) do |arg|
11
- #do something for :baz
12
- end
7
+ obj.stub(:foo).with(:bar) do |arg|
8
+ #do something for :bar
9
+ end
10
+ obj.stub(:foo).with(:baz) do |arg|
11
+ #do something for :baz
12
+ end
13
13
 
14
14
  * In expectations to validate the arguments that should be received in a method call
15
15
 
16
- #create a double
17
- obj = double()
16
+ #create a double
17
+ obj = double()
18
18
 
19
- #expect a message with given args
20
- obj.should_receive(:message).with('an argument')
19
+ #expect a message with given args
20
+ obj.should_receive(:message).with('an argument')
21
21
 
22
22
  If more control is needed, one can use a block
23
23
 
@@ -1,6 +1,8 @@
1
1
  Feature: stub with argument constraints
2
2
 
3
- You can further specify the behavior by constraining the type, format and/or number of arguments with the #with() method chained off of #stub()
3
+ You can further specify the behavior by constraining the type,
4
+ format and/or number of arguments with the `#with()` method
5
+ chained off of `#stub()`
4
6
 
5
7
  Scenario: an_instance_of argument matcher
6
8
  Given a file named "stub_an_instance_of_args_spec.rb" with:
@@ -7,7 +7,30 @@
7
7
  obj.should_receive(:message)
8
8
 
9
9
  # specify a return value
10
- obj.should_receive(:message) { 'this is the value to return' }
10
+ obj.should_receive(:message) { :value }
11
+ obj.should_receive(:message => :value)
12
+ obj.should_receive(:message).and_return(:value)
13
+
14
+ These forms are somewhat interchangeable. The difference is that the
15
+ block contents are evaluated lazily when the `obj` receives the
16
+ `message` message, whereas the others are evaluated as they are read.
17
+
18
+ ### Fake implementation
19
+
20
+ obj.should_receive(:message) do |arg1, arg2|
21
+ # set expectations about the args in this block
22
+ # and set a return value
23
+ end
24
+
25
+ ### Raising/Throwing
26
+
27
+ obj.should_receive(:message).and_raise("this error")
28
+ obj.should_receive(:message).and_throw(:this_symbol)
29
+
30
+ You can also use the block format:
31
+
32
+ obj.should_receive(:message) { raise "this error" }
33
+ obj.should_receive(:message) { throw :this_symbol }
11
34
 
12
35
  ### Argument constraints
13
36
 
@@ -40,19 +63,7 @@
40
63
  obj.should_receive(:message).at_most(:twice)
41
64
  obj.should_receive(:message).at_most(n).times
42
65
 
43
- ### Raising/Throwing
44
-
45
- obj.should_receive(:message) { raise "this error" }
46
- obj.should_receive(:message) { throw :this_symbol }
47
-
48
66
  ### Ordering
49
67
 
50
68
  obj.should_receive(:one).ordered
51
69
  obj.should_receive(:two).ordered
52
-
53
- ### Arbitrary handling
54
-
55
- obj.should_receive(:message) do |arg1, arg2|
56
- # set expectations about the args in this block
57
- # and set a return value
58
- end
@@ -1,12 +1,16 @@
1
1
  ### Stub return values
2
2
 
3
+ # create a double
4
+ obj = double()
5
+
6
+ # specify a return value
3
7
  obj.stub(:message) { :value }
4
8
  obj.stub(:message => :value)
5
9
  obj.stub(:message).and_return(:value)
6
10
 
7
- These forms are somewhat interchangeable. The difference is that the block
8
- contents are evaluated lazily when the `obj` receives the `message` message,
9
- whereas the others are evaluated as they are read.
11
+ These forms are somewhat interchangeable. The difference is that the
12
+ block contents are evaluated lazily when the `obj` receives the
13
+ `message` message, whereas the others are evaluated as they are read.
10
14
 
11
15
  ### Fake implementation
12
16
 
@@ -20,7 +24,7 @@ whereas the others are evaluated as they are read.
20
24
  obj.stub(:message).and_raise("this error")
21
25
  obj.stub(:message).and_throw(:this_symbol)
22
26
 
23
- You can also use the block format, for consistency with other stubs:
27
+ You can also use the block format:
24
28
 
25
29
  obj.stub(:message) { raise "this error" }
26
30
  obj.stub(:message) { throw :this_symbol }
@@ -54,7 +54,7 @@ module RSpec
54
54
 
55
55
  private
56
56
  def modify_dup_to_remove_mock_proxy_when_invoked
57
- unless self.method_defined?(:__rspec_original_dup)
57
+ if self.method_defined?(:dup) and !self.method_defined?(:__rspec_original_dup)
58
58
  self.class_eval do
59
59
  def __rspec_dup
60
60
  __remove_mock_proxy
@@ -175,7 +175,8 @@ module RSpec
175
175
  backup_method!(method_name)
176
176
  @klass.class_eval(<<-EOM, __FILE__, __LINE__)
177
177
  def #{method_name}(*args, &blk)
178
- self.class.__recorder.playback!(self, :#{method_name})
178
+ klass = self.method(:#{method_name}).owner
179
+ klass.__recorder.playback!(self, :#{method_name})
179
180
  self.__send__(:#{method_name}, *args, &blk)
180
181
  end
181
182
  EOM
@@ -186,7 +187,8 @@ module RSpec
186
187
  @klass.class_eval(<<-EOM, __FILE__, __LINE__)
187
188
  def #{method_name}(*args, &blk)
188
189
  method_name = :#{method_name}
189
- invoked_instance = self.class.__recorder.instance_that_received(method_name)
190
+ klass = self.method(:#{method_name}).owner
191
+ invoked_instance = klass.__recorder.instance_that_received(method_name)
190
192
  raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by \#{self.inspect} but has already been received by \#{invoked_instance}"
191
193
  end
192
194
  EOM
@@ -31,7 +31,7 @@ module RSpec
31
31
  def raise_missing_default_stub_error(expectation,*args)
32
32
  expected_args = format_args(*expectation.expected_args)
33
33
  actual_args = args.collect {|a| format_args(*a)}.join(", ")
34
- __raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n Please stub a default value first if message might be received with other args as well. \n"
34
+ __raise "#{intro} received #{expectation.message.inspect} with unexpected arguments\n expected: #{expected_args}\n got: #{actual_args}\n Please stub a default value first if message might be received with other args as well. \n"
35
35
  end
36
36
 
37
37
  # @private
@@ -4,15 +4,54 @@ module RSpec
4
4
  # constant stubbing.
5
5
  # @api private
6
6
  module RecursiveConstMethods
7
- def recursive_const_get(name)
8
- name.split('::').inject(Object) { |mod, name| mod.const_get name }
7
+ # We only want to consider constants that are defined directly on a
8
+ # particular module, and not include top-level/inherited constants.
9
+ # Unfortunately, the constant API changed between 1.8 and 1.9, so
10
+ # we need to conditionally define methods to ignore the top-level/inherited
11
+ # constants.
12
+ #
13
+ # Given `class A; end`:
14
+ #
15
+ # On 1.8:
16
+ # - A.const_get("Hash") # => ::Hash
17
+ # - A.const_defined?("Hash") # => false
18
+ # - Neither method accepts the extra `inherit` argument
19
+ # On 1.9:
20
+ # - A.const_get("Hash") # => ::Hash
21
+ # - A.const_defined?("Hash") # => true
22
+ # - A.const_get("Hash", false) # => raises NameError
23
+ # - A.const_defined?("Hash", false) # => false
24
+ if Module.method(:const_defined?).arity == 1
25
+ def const_defined_on?(mod, const_name)
26
+ mod.const_defined?(const_name)
27
+ end
28
+
29
+ def get_const_defined_on(mod, const_name)
30
+ if const_defined_on?(mod, const_name)
31
+ return mod.const_get(const_name)
32
+ end
33
+
34
+ raise NameError, "uninitialized constant #{mod.name}::#{const_name}"
35
+ end
36
+ else
37
+ def const_defined_on?(mod, const_name)
38
+ mod.const_defined?(const_name, false)
39
+ end
40
+
41
+ def get_const_defined_on(mod, const_name)
42
+ mod.const_get(const_name, false)
43
+ end
44
+ end
45
+
46
+ def recursive_const_get(const_name)
47
+ const_name.split('::').inject(Object) { |mod, name| get_const_defined_on(mod, name) }
9
48
  end
10
49
 
11
- def recursive_const_defined?(name)
12
- name.split('::').inject([Object, '']) do |(mod, full_name), name|
50
+ def recursive_const_defined?(const_name)
51
+ const_name.split('::').inject([Object, '']) do |(mod, full_name), name|
13
52
  yield(full_name, name) if block_given? && !mod.is_a?(Module)
14
- return false unless mod.const_defined?(name)
15
- [mod.const_get(name), [mod, name].join('::')]
53
+ return false unless const_defined_on?(mod, name)
54
+ [get_const_defined_on(mod, name), [mod, name].join('::')]
16
55
  end
17
56
  end
18
57
  end
@@ -139,7 +178,7 @@ module RSpec
139
178
  class DefinedConstantReplacer < BaseStubber
140
179
  def stub
141
180
  @context = recursive_const_get(@context_parts.join('::'))
142
- @original_value = @context.const_get(@const_name)
181
+ @original_value = get_const_defined_on(@context, @const_name)
143
182
 
144
183
  constants_to_transfer = verify_constants_to_transfer!
145
184
 
@@ -160,7 +199,7 @@ module RSpec
160
199
 
161
200
  def transfer_nested_constants(constants)
162
201
  constants.each do |const|
163
- @stubbed_value.const_set(const, original_value.const_get(const))
202
+ @stubbed_value.const_set(const, get_const_defined_on(original_value, const))
164
203
  end
165
204
  end
166
205
 
@@ -202,9 +241,9 @@ module RSpec
202
241
  def stub
203
242
  remaining_parts = @context_parts.dup
204
243
  @deepest_defined_const = @context_parts.inject(Object) do |klass, name|
205
- break klass unless klass.const_defined?(name)
244
+ break klass unless const_defined_on?(klass, name)
206
245
  remaining_parts.shift
207
- klass.const_get(name)
246
+ get_const_defined_on(klass, name)
208
247
  end
209
248
 
210
249
  context = remaining_parts.inject(@deepest_defined_const) do |klass, name|
@@ -230,7 +269,7 @@ module RSpec
230
269
  #
231
270
  # @api private
232
271
  def self.ensure_registered_with_mocks_space
233
- return if @registered_with_mocks_space
272
+ return if defined?(@registered_with_mocks_space) && @registered_with_mocks_space
234
273
  ::RSpec::Mocks.space.add(self)
235
274
  @registered_with_mocks_space = true
236
275
  end
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Mocks
3
3
  module Version
4
- STRING = '2.11.1'
4
+ STRING = '2.11.2'
5
5
  end
6
6
  end
7
7
  end
@@ -818,8 +818,33 @@ module RSpec
818
818
  o.some_method
819
819
  lambda { o.dup.some_method }.should_not raise_error(SystemStackError)
820
820
  end
821
+
822
+ it "doesn't bomb if the object doesn't support `dup`" do
823
+ klass = Class.new do
824
+ undef_method :dup
825
+ end
826
+ klass.any_instance
827
+ end
821
828
  end
822
829
 
830
+ context "when directed at a method defined on a superclass" do
831
+ let(:sub_klass) { Class.new(klass) }
832
+
833
+ it "stubs the method correctly" do
834
+ klass.any_instance.stub(:existing_method).and_return("foo")
835
+ sub_klass.new.existing_method.should == "foo"
836
+ end
837
+
838
+ it "mocks the method correctly" do
839
+ instance_one = sub_klass.new
840
+ instance_two = sub_klass.new
841
+ expect do
842
+ klass.any_instance.should_receive(:existing_method)
843
+ instance_one.existing_method
844
+ instance_two.existing_method
845
+ end.to raise_error(RSpec::Mocks::MockExpectationError, "The message 'existing_method' was received by #{instance_two.inspect} but has already been received by #{instance_one.inspect}")
846
+ end
847
+ end
823
848
  end
824
849
  end
825
850
  end
@@ -57,7 +57,6 @@ module RSpec
57
57
  end
58
58
 
59
59
  it 'returns the stubbed value' do
60
- orig_value = const
61
60
  stub_const(const_name, 7).should eq(7)
62
61
  end
63
62
  end
@@ -178,6 +177,10 @@ module RSpec
178
177
  it_behaves_like "loaded constant stubbing", "TestClass::Nested"
179
178
  end
180
179
 
180
+ context 'for an unloaded constant with nested name that matches a top-level constant' do
181
+ it_behaves_like "unloaded constant stubbing", "TestClass::Hash"
182
+ end
183
+
181
184
  context 'for a loaded deeply nested constant' do
182
185
  it_behaves_like "loaded constant stubbing", "TestClass::Nested::NestedEvenMore"
183
186
  end
metadata CHANGED
@@ -1,80 +1,71 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rspec-mocks
3
- version: !ruby/object:Gem::Version
4
- hash: 33
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.11.2
5
5
  prerelease:
6
- segments:
7
- - 2
8
- - 11
9
- - 1
10
- version: 2.11.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Steven Baker
14
9
  - David Chelimsky
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2012-07-10 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-08-12 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.2
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
26
  none: false
27
- requirements:
27
+ requirements:
28
28
  - - ~>
29
- - !ruby/object:Gem::Version
30
- hash: 63
31
- segments:
32
- - 0
33
- - 9
34
- - 2
29
+ - !ruby/object:Gem::Version
35
30
  version: 0.9.2
36
- requirement: *id001
37
- - !ruby/object:Gem::Dependency
31
+ - !ruby/object:Gem::Dependency
38
32
  name: cucumber
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 1.1.9
39
39
  type: :development
40
40
  prerelease: false
41
- version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
42
42
  none: false
43
- requirements:
43
+ requirements:
44
44
  - - ~>
45
- - !ruby/object:Gem::Version
46
- hash: 1
47
- segments:
48
- - 1
49
- - 1
50
- - 9
45
+ - !ruby/object:Gem::Version
51
46
  version: 1.1.9
52
- requirement: *id002
53
- - !ruby/object:Gem::Dependency
47
+ - !ruby/object:Gem::Dependency
54
48
  name: aruba
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.4.11
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: &id003 !ruby/object:Gem::Requirement
57
+ version_requirements: !ruby/object:Gem::Requirement
58
58
  none: false
59
- requirements:
59
+ requirements:
60
60
  - - ~>
61
- - !ruby/object:Gem::Version
62
- hash: 25
63
- segments:
64
- - 0
65
- - 4
66
- - 11
61
+ - !ruby/object:Gem::Version
67
62
  version: 0.4.11
68
- requirement: *id003
69
63
  description: RSpec's 'test double' framework, with support for stubbing and mocking
70
64
  email: rspec-users@rubyforge.org
71
65
  executables: []
72
-
73
66
  extensions: []
74
-
75
67
  extra_rdoc_files: []
76
-
77
- files:
68
+ files:
78
69
  - lib/rspec/mocks.rb
79
70
  - lib/rspec/mocks/any_instance.rb
80
71
  - lib/rspec/mocks/any_instance/chain.rb
@@ -184,39 +175,38 @@ files:
184
175
  - spec/rspec/mocks_spec.rb
185
176
  - spec/spec_helper.rb
186
177
  homepage: http://github.com/rspec/rspec-mocks
187
- licenses:
178
+ licenses:
188
179
  - MIT
189
180
  post_install_message:
190
- rdoc_options:
181
+ rdoc_options:
191
182
  - --charset=UTF-8
192
- require_paths:
183
+ require_paths:
193
184
  - lib
194
- required_ruby_version: !ruby/object:Gem::Requirement
185
+ required_ruby_version: !ruby/object:Gem::Requirement
195
186
  none: false
196
- requirements:
197
- - - ">="
198
- - !ruby/object:Gem::Version
199
- hash: 3
200
- segments:
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ segments:
201
192
  - 0
202
- version: "0"
203
- required_rubygems_version: !ruby/object:Gem::Requirement
193
+ hash: -769108312098701241
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
204
195
  none: false
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- hash: 3
209
- segments:
196
+ requirements:
197
+ - - ! '>='
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ segments:
210
201
  - 0
211
- version: "0"
202
+ hash: -769108312098701241
212
203
  requirements: []
213
-
214
204
  rubyforge_project: rspec
215
- rubygems_version: 1.8.6
205
+ rubygems_version: 1.8.24
216
206
  signing_key:
217
207
  specification_version: 3
218
- summary: rspec-mocks-2.11.1
219
- test_files:
208
+ summary: rspec-mocks-2.11.2
209
+ test_files:
220
210
  - features/README.md
221
211
  - features/Scope.md
222
212
  - features/Upgrade.md