mocha 1.14.0 → 2.0.0.alpha
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 +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile +3 -5
- data/README.md +1 -1
- data/RELEASE.md +52 -0
- data/Rakefile +19 -20
- data/gemfiles/Gemfile.test-unit.latest +1 -5
- data/lib/mocha/any_instance_method.rb +0 -5
- data/lib/mocha/api.rb +29 -78
- data/lib/mocha/class_methods.rb +2 -2
- data/lib/mocha/configuration.rb +30 -108
- data/lib/mocha/expectation.rb +55 -7
- data/lib/mocha/inspect.rb +2 -2
- data/lib/mocha/instance_method.rb +0 -4
- data/lib/mocha/integration/mini_test.rb +10 -38
- data/lib/mocha/integration/test_unit/adapter.rb +1 -1
- data/lib/mocha/integration/test_unit.rb +10 -33
- data/lib/mocha/invocation.rb +12 -16
- data/lib/mocha/minitest.rb +2 -4
- data/lib/mocha/mock.rb +22 -26
- data/lib/mocha/mockery.rb +1 -3
- data/lib/mocha/parameter_matchers/equivalent_uri.rb +0 -1
- data/lib/mocha/parameter_matchers/instance_methods.rb +9 -0
- data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +56 -0
- data/lib/mocha/parameters_matcher.rb +0 -1
- data/lib/mocha/ruby_version.rb +1 -2
- data/lib/mocha/stubbed_method.rb +5 -42
- data/lib/mocha/test_unit.rb +2 -4
- data/lib/mocha/version.rb +1 -1
- data/lib/mocha.rb +0 -8
- data/mocha.gemspec +1 -1
- metadata +7 -27
- data/init.rb +0 -1
- data/lib/mocha/integration/mini_test/nothing.rb +0 -19
- data/lib/mocha/integration/mini_test/version_13.rb +0 -54
- data/lib/mocha/integration/mini_test/version_140.rb +0 -54
- data/lib/mocha/integration/mini_test/version_141.rb +0 -65
- data/lib/mocha/integration/mini_test/version_142_to_172.rb +0 -65
- data/lib/mocha/integration/mini_test/version_200.rb +0 -66
- data/lib/mocha/integration/mini_test/version_201_to_222.rb +0 -66
- data/lib/mocha/integration/mini_test/version_2110_to_2111.rb +0 -70
- data/lib/mocha/integration/mini_test/version_2112_to_320.rb +0 -73
- data/lib/mocha/integration/mini_test/version_230_to_2101.rb +0 -68
- data/lib/mocha/integration/test_unit/gem_version_200.rb +0 -62
- data/lib/mocha/integration/test_unit/gem_version_201_to_202.rb +0 -62
- data/lib/mocha/integration/test_unit/gem_version_203_to_220.rb +0 -62
- data/lib/mocha/integration/test_unit/gem_version_230_to_250.rb +0 -68
- data/lib/mocha/integration/test_unit/nothing.rb +0 -19
- data/lib/mocha/integration/test_unit/ruby_version_185_and_below.rb +0 -61
- data/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb +0 -63
- data/lib/mocha/integration.rb +0 -11
- data/lib/mocha/setup.rb +0 -14
- data/lib/mocha/singleton_class.rb +0 -9
data/lib/mocha/expectation.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ruby2_keywords'
|
1
2
|
require 'mocha/method_matcher'
|
2
3
|
require 'mocha/parameters_matcher'
|
3
4
|
require 'mocha/expectation_error'
|
@@ -187,17 +188,26 @@ module Mocha
|
|
187
188
|
at_most(1)
|
188
189
|
end
|
189
190
|
|
190
|
-
# Modifies expectation so that the expected method must be called with +
|
191
|
+
# Modifies expectation so that the expected method must be called with +expected_parameters_or_matchers+.
|
191
192
|
#
|
192
|
-
# May be used with parameter matchers
|
193
|
+
# May be used with Ruby literals or variables for exact matching or with parameter matchers for less-specific matching, e.g. {ParameterMatchers#includes}, {ParameterMatchers#has_key}, etc. See {ParameterMatchers} for a list of all available parameter matchers.
|
193
194
|
#
|
194
|
-
#
|
195
|
+
# Positional arguments were separated from keyword arguments in Ruby v3 (see {https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0 this article}). In relation to this a new configuration option ({Configuration#strict_keyword_argument_matching=}) is available in Ruby >= 2.7.
|
196
|
+
#
|
197
|
+
# When {Configuration#strict_keyword_argument_matching=} is set to +false+ (which is currently the default), a positional +Hash+ and a set of keyword arguments passed to {#with} are treated the same for the purposes of parameter matching. However, a deprecation warning will be displayed if a positional +Hash+ matches a set of keyword arguments or vice versa. This is because {Configuration#strict_keyword_argument_matching=} will default to +true+ in the future.
|
198
|
+
#
|
199
|
+
# When {Configuration#strict_keyword_argument_matching=} is set to +true+, an actual positional +Hash+ will not match an expected set of keyword arguments; and vice versa, an actual set of keyword arguments will not match an expected positional +Hash+, i.e. the parameter matching is stricter.
|
200
|
+
#
|
201
|
+
# @see ParameterMatchers
|
202
|
+
# @see Configuration#strict_keyword_argument_matching=
|
203
|
+
#
|
204
|
+
# @param [*Array<Object,ParameterMatchers::Base>] expected_parameters_or_matchers expected parameter values or parameter matchers.
|
195
205
|
# @yield optional block specifying custom matching.
|
196
|
-
# @yieldparam [*Array] actual_parameters parameters with which expected method was invoked.
|
206
|
+
# @yieldparam [*Array<Object>] actual_parameters parameters with which expected method was invoked.
|
197
207
|
# @yieldreturn [Boolean] +true+ if +actual_parameters+ are acceptable.
|
198
208
|
# @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
|
199
209
|
#
|
200
|
-
# @example Expected method must be called with
|
210
|
+
# @example Expected method must be called with exact parameter values.
|
201
211
|
# object = mock()
|
202
212
|
# object.expects(:expected_method).with(:param1, :param2)
|
203
213
|
# object.expected_method(:param1, :param2)
|
@@ -208,6 +218,43 @@ module Mocha
|
|
208
218
|
# object.expected_method(:param3)
|
209
219
|
# # => verify fails
|
210
220
|
#
|
221
|
+
# @example Expected method must be called with parameters matching parameter matchers.
|
222
|
+
# object = mock()
|
223
|
+
# object.expects(:expected_method).with(includes('string2'), anything)
|
224
|
+
# object.expected_method(['string1', 'string2'], 'any-old-value')
|
225
|
+
# # => verify succeeds
|
226
|
+
#
|
227
|
+
# object = mock()
|
228
|
+
# object.expects(:expected_method).with(includes('string2'), anything)
|
229
|
+
# object.expected_method(['string1'], 'any-old-value')
|
230
|
+
# # => verify fails
|
231
|
+
#
|
232
|
+
# @example Loose keyword argument matching (default)
|
233
|
+
#
|
234
|
+
# class Example
|
235
|
+
# def foo(a, bar:); end
|
236
|
+
# end
|
237
|
+
#
|
238
|
+
# example = Example.new
|
239
|
+
# example.expects(:foo).with('a', bar: 'b')
|
240
|
+
# example.foo('a', { bar: 'b' })
|
241
|
+
# # This passes the test, but would result in an ArgumentError in practice
|
242
|
+
#
|
243
|
+
# @example Strict keyword argument matching
|
244
|
+
#
|
245
|
+
# Mocha.configure do |c|
|
246
|
+
# c.strict_keyword_argument_matching = true
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# class Example
|
250
|
+
# def foo(a, bar:); end
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# example = Example.new
|
254
|
+
# example.expects(:foo).with('a', bar: 'b')
|
255
|
+
# example.foo('a', { bar: 'b' })
|
256
|
+
# # This now fails as expected
|
257
|
+
#
|
211
258
|
# @example Expected method must be called with a value divisible by 4.
|
212
259
|
# object = mock()
|
213
260
|
# object.expects(:expected_method).with() { |value| value % 4 == 0 }
|
@@ -218,10 +265,11 @@ module Mocha
|
|
218
265
|
# object.expects(:expected_method).with() { |value| value % 4 == 0 }
|
219
266
|
# object.expected_method(17)
|
220
267
|
# # => verify fails
|
221
|
-
def with(*
|
222
|
-
@parameters_matcher = ParametersMatcher.new(
|
268
|
+
def with(*expected_parameters_or_matchers, &matching_block)
|
269
|
+
@parameters_matcher = ParametersMatcher.new(expected_parameters_or_matchers, &matching_block)
|
223
270
|
self
|
224
271
|
end
|
272
|
+
ruby2_keywords(:with)
|
225
273
|
|
226
274
|
# Modifies expectation so that the expected method must be called with a block.
|
227
275
|
#
|
data/lib/mocha/inspect.rb
CHANGED
@@ -18,9 +18,9 @@ module Mocha
|
|
18
18
|
end
|
19
19
|
|
20
20
|
module HashMethods
|
21
|
-
def mocha_inspect
|
21
|
+
def mocha_inspect
|
22
22
|
unwrapped = collect { |key, value| "#{key.mocha_inspect} => #{value.mocha_inspect}" }.join(', ')
|
23
|
-
|
23
|
+
Hash.ruby2_keywords_hash?(self) ? unwrapped : "{#{unwrapped}}"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -1,54 +1,26 @@
|
|
1
1
|
require 'mocha/debug'
|
2
|
-
|
3
2
|
require 'mocha/detection/mini_test'
|
4
|
-
|
5
|
-
require 'mocha/integration/mini_test/nothing'
|
6
|
-
require 'mocha/integration/mini_test/version_13'
|
7
|
-
require 'mocha/integration/mini_test/version_140'
|
8
|
-
require 'mocha/integration/mini_test/version_141'
|
9
|
-
require 'mocha/integration/mini_test/version_142_to_172'
|
10
|
-
require 'mocha/integration/mini_test/version_200'
|
11
|
-
require 'mocha/integration/mini_test/version_201_to_222'
|
12
|
-
require 'mocha/integration/mini_test/version_230_to_2101'
|
13
|
-
require 'mocha/integration/mini_test/version_2110_to_2111'
|
14
|
-
require 'mocha/integration/mini_test/version_2112_to_320'
|
15
3
|
require 'mocha/integration/mini_test/adapter'
|
16
4
|
|
17
|
-
require 'mocha/deprecation'
|
18
|
-
|
19
5
|
module Mocha
|
20
6
|
module Integration
|
21
7
|
module MiniTest
|
22
8
|
def self.activate
|
23
|
-
|
24
|
-
|
9
|
+
target = Detection::MiniTest.testcase
|
10
|
+
return false unless target
|
25
11
|
|
12
|
+
mini_test_version = Gem::Version.new(Detection::MiniTest.version)
|
26
13
|
Debug.puts "Detected MiniTest version: #{mini_test_version}"
|
27
14
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
MiniTest::Version2110To2111,
|
32
|
-
MiniTest::Version230To2101,
|
33
|
-
MiniTest::Version201To222,
|
34
|
-
MiniTest::Version200,
|
35
|
-
MiniTest::Version142To172,
|
36
|
-
MiniTest::Version141,
|
37
|
-
MiniTest::Version140,
|
38
|
-
MiniTest::Version13,
|
39
|
-
MiniTest::Nothing
|
40
|
-
].detect { |m| m.applicable_to?(mini_test_version) }
|
15
|
+
unless MiniTest::Adapter.applicable_to?(mini_test_version)
|
16
|
+
raise 'Versions of minitest earlier than v3.3.0 are not supported.'
|
17
|
+
end
|
41
18
|
|
42
|
-
target
|
43
|
-
|
44
|
-
|
45
|
-
Deprecation.warning(
|
46
|
-
'Versions of minitest earlier than v3.3.0 will not be supported in future versions of Mocha.'
|
47
|
-
)
|
48
|
-
end
|
49
|
-
Debug.puts "Applying #{integration_module.description}"
|
50
|
-
target.send(:include, integration_module)
|
19
|
+
unless target < MiniTest::Adapter
|
20
|
+
Debug.puts "Applying #{MiniTest::Adapter.description}"
|
21
|
+
target.send(:include, MiniTest::Adapter)
|
51
22
|
end
|
23
|
+
|
52
24
|
true
|
53
25
|
end
|
54
26
|
end
|
@@ -1,49 +1,26 @@
|
|
1
1
|
require 'mocha/debug'
|
2
|
-
|
3
2
|
require 'mocha/detection/test_unit'
|
4
|
-
|
5
|
-
require 'mocha/integration/test_unit/nothing'
|
6
|
-
require 'mocha/integration/test_unit/ruby_version_185_and_below'
|
7
|
-
require 'mocha/integration/test_unit/ruby_version_186_and_above'
|
8
|
-
require 'mocha/integration/test_unit/gem_version_200'
|
9
|
-
require 'mocha/integration/test_unit/gem_version_201_to_202'
|
10
|
-
require 'mocha/integration/test_unit/gem_version_203_to_220'
|
11
|
-
require 'mocha/integration/test_unit/gem_version_230_to_250'
|
12
3
|
require 'mocha/integration/test_unit/adapter'
|
13
4
|
|
14
|
-
require 'mocha/deprecation'
|
15
|
-
|
16
5
|
module Mocha
|
17
6
|
module Integration
|
18
7
|
module TestUnit
|
19
8
|
def self.activate
|
20
|
-
|
21
|
-
|
22
|
-
ruby_version = Gem::Version.new(RUBY_VERSION.dup)
|
9
|
+
target = Detection::TestUnit.testcase
|
10
|
+
return false unless target
|
23
11
|
|
24
|
-
|
12
|
+
test_unit_version = Gem::Version.new(Detection::TestUnit.version)
|
25
13
|
Debug.puts "Detected Test::Unit version: #{test_unit_version}"
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
TestUnit::GemVersion203To220,
|
31
|
-
TestUnit::GemVersion201To202,
|
32
|
-
TestUnit::GemVersion200,
|
33
|
-
TestUnit::RubyVersion186AndAbove,
|
34
|
-
TestUnit::RubyVersion185AndBelow,
|
35
|
-
TestUnit::Nothing
|
36
|
-
].detect { |m| m.applicable_to?(test_unit_version, ruby_version) }
|
15
|
+
unless TestUnit::Adapter.applicable_to?(test_unit_version)
|
16
|
+
raise 'Versions of test-unit earlier than v2.5.1 are not supported.'
|
17
|
+
end
|
37
18
|
|
38
|
-
unless
|
39
|
-
|
40
|
-
|
41
|
-
'Versions of test-unit earlier than v2.5.1 will not be supported in future versions of Mocha.'
|
42
|
-
)
|
43
|
-
end
|
44
|
-
Debug.puts "Applying #{integration_module.description}"
|
45
|
-
::Test::Unit::TestCase.send(:include, integration_module)
|
19
|
+
unless target < TestUnit::Adapter
|
20
|
+
Debug.puts "Applying #{TestUnit::Adapter.description}"
|
21
|
+
target.send(:include, TestUnit::Adapter)
|
46
22
|
end
|
23
|
+
|
47
24
|
true
|
48
25
|
end
|
49
26
|
end
|
data/lib/mocha/invocation.rb
CHANGED
@@ -3,14 +3,12 @@ require 'mocha/raised_exception'
|
|
3
3
|
require 'mocha/return_values'
|
4
4
|
require 'mocha/thrown_object'
|
5
5
|
require 'mocha/yield_parameters'
|
6
|
-
require 'mocha/configuration'
|
7
|
-
require 'mocha/deprecation'
|
8
6
|
|
9
7
|
module Mocha
|
10
8
|
class Invocation
|
11
9
|
attr_reader :method_name, :block
|
12
10
|
|
13
|
-
def initialize(mock, method_name,
|
11
|
+
def initialize(mock, method_name, arguments = [], block = nil)
|
14
12
|
@mock = mock
|
15
13
|
@method_name = method_name
|
16
14
|
@arguments = arguments
|
@@ -22,18 +20,8 @@ module Mocha
|
|
22
20
|
def call(yield_parameters = YieldParameters.new, return_values = ReturnValues.new)
|
23
21
|
yield_parameters.next_invocation.each do |yield_args|
|
24
22
|
@yields << ParametersMatcher.new(yield_args)
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
raise LocalJumpError unless Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
|
29
|
-
yield_args_description = ParametersMatcher.new(yield_args).mocha_inspect
|
30
|
-
Deprecation.warning(
|
31
|
-
"Stubbed method was instructed to yield #{yield_args_description}, but no block was given by invocation: #{call_description}.",
|
32
|
-
' This will raise a LocalJumpError in the future.',
|
33
|
-
' Use Expectation#with_block_given to constrain this expectation to match invocations supplying a block.',
|
34
|
-
' And, if necessary, add another expectation to match invocations not supplying a block.'
|
35
|
-
)
|
36
|
-
end
|
23
|
+
raise LocalJumpError unless @block
|
24
|
+
@block.call(*yield_args)
|
37
25
|
end
|
38
26
|
return_values.next(self)
|
39
27
|
end
|
@@ -55,7 +43,7 @@ module Mocha
|
|
55
43
|
end
|
56
44
|
|
57
45
|
def call_description
|
58
|
-
description = "#{@mock.mocha_inspect}.#{@method_name}#{
|
46
|
+
description = "#{@mock.mocha_inspect}.#{@method_name}#{argument_description}"
|
59
47
|
description << ' { ... }' unless @block.nil?
|
60
48
|
description
|
61
49
|
end
|
@@ -73,5 +61,13 @@ module Mocha
|
|
73
61
|
def full_description
|
74
62
|
"\n - #{call_description} #{result_description}"
|
75
63
|
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def argument_description
|
68
|
+
signature = arguments.mocha_inspect
|
69
|
+
signature = signature.gsub(/^\[|\]$/, '')
|
70
|
+
"(#{signature})"
|
71
|
+
end
|
76
72
|
end
|
77
73
|
end
|
data/lib/mocha/minitest.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
+
require 'mocha/ruby_version'
|
1
2
|
require 'mocha/integration/mini_test'
|
2
|
-
require 'mocha/deprecation'
|
3
3
|
|
4
4
|
unless Mocha::Integration::MiniTest.activate
|
5
|
-
|
6
|
-
"MiniTest must be loaded *before* `require 'mocha/minitest'`."
|
7
|
-
)
|
5
|
+
raise "MiniTest must be loaded *before* `require 'mocha/minitest'`."
|
8
6
|
end
|
data/lib/mocha/mock.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'ruby2_keywords'
|
2
2
|
require 'mocha/expectation'
|
3
3
|
require 'mocha/expectation_list'
|
4
4
|
require 'mocha/invocation'
|
@@ -8,7 +8,6 @@ require 'mocha/method_matcher'
|
|
8
8
|
require 'mocha/parameters_matcher'
|
9
9
|
require 'mocha/argument_iterator'
|
10
10
|
require 'mocha/expectation_error_factory'
|
11
|
-
require 'mocha/ruby_version'
|
12
11
|
|
13
12
|
module Mocha
|
14
13
|
# Traditional mock object.
|
@@ -165,7 +164,7 @@ module Mocha
|
|
165
164
|
# @param [Array<Symbol>] method_names names of methods to unstub.
|
166
165
|
#
|
167
166
|
# @example Invoking an unstubbed method causes error to be raised
|
168
|
-
# object = mock('mock')
|
167
|
+
# object = mock('mock')
|
169
168
|
# object.stubs(:stubbed_method).returns(:result_one)
|
170
169
|
# object.stubbed_method # => :result_one
|
171
170
|
# object.unstub(:stubbed_method)
|
@@ -310,10 +309,18 @@ module Mocha
|
|
310
309
|
end
|
311
310
|
|
312
311
|
# @private
|
313
|
-
|
312
|
+
# rubocop:disable Style/MethodMissingSuper
|
313
|
+
def method_missing(symbol, *arguments, &block)
|
314
|
+
handle_method_call(symbol, arguments, block)
|
315
|
+
end
|
316
|
+
ruby2_keywords(:method_missing)
|
317
|
+
# rubocop:enable Style/MethodMissingSuper
|
318
|
+
|
319
|
+
# @private
|
320
|
+
def handle_method_call(symbol, arguments, block)
|
314
321
|
check_expiry
|
315
322
|
check_responder_responds_to(symbol)
|
316
|
-
invocation = Invocation.new(self, symbol,
|
323
|
+
invocation = Invocation.new(self, symbol, arguments, block)
|
317
324
|
if (matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(invocation))
|
318
325
|
matching_expectation_allowing_invocation.invoke(invocation)
|
319
326
|
elsif (matching_expectation = all_expectations.match(invocation)) || (!matching_expectation && !@everything_stubbed)
|
@@ -322,25 +329,14 @@ module Mocha
|
|
322
329
|
end
|
323
330
|
|
324
331
|
# @private
|
325
|
-
def respond_to_missing?(symbol,
|
332
|
+
def respond_to_missing?(symbol, include_all)
|
326
333
|
if @responder
|
327
|
-
|
328
|
-
@responder.respond_to?(symbol, include_private)
|
329
|
-
else
|
330
|
-
@responder.respond_to?(symbol)
|
331
|
-
end
|
334
|
+
@responder.respond_to?(symbol, include_all)
|
332
335
|
else
|
333
336
|
@everything_stubbed || all_expectations.matches_method?(symbol)
|
334
337
|
end
|
335
338
|
end
|
336
339
|
|
337
|
-
if PRE_RUBY_V19
|
338
|
-
# @private
|
339
|
-
def respond_to?(symbol, include_private = false)
|
340
|
-
respond_to_missing?(symbol, include_private)
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
340
|
# @private
|
345
341
|
def __verified__?(assertion_counter = nil)
|
346
342
|
@expectations.verified?(assertion_counter)
|
@@ -391,14 +387,14 @@ module Mocha
|
|
391
387
|
end
|
392
388
|
|
393
389
|
def check_expiry
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
390
|
+
return unless @expired
|
391
|
+
|
392
|
+
sentences = [
|
393
|
+
"#{mocha_inspect} was instantiated in one test but it is receiving invocations within another test.",
|
394
|
+
'This can lead to unintended interactions between tests and hence unexpected test failures.',
|
395
|
+
'Ensure that every test correctly cleans up any state that it introduces.'
|
396
|
+
]
|
397
|
+
raise StubbingError.new(sentences.join(' '), caller)
|
402
398
|
end
|
403
399
|
end
|
404
400
|
end
|
data/lib/mocha/mockery.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'mocha/ruby_version'
|
2
1
|
require 'mocha/central'
|
3
2
|
require 'mocha/mock'
|
4
3
|
require 'mocha/names'
|
@@ -119,10 +118,9 @@ module Mocha
|
|
119
118
|
end
|
120
119
|
|
121
120
|
def on_stubbing(object, method)
|
122
|
-
method = PRE_RUBY_V19 ? method.to_s : method.to_sym
|
123
121
|
signature_proc = lambda { "#{object.mocha_inspect}.#{method}" }
|
124
122
|
check(:stubbing_non_existent_method, 'non-existent method', signature_proc) do
|
125
|
-
!(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method
|
123
|
+
!(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method))
|
126
124
|
end
|
127
125
|
check(:stubbing_non_public_method, 'non-public method', signature_proc) do
|
128
126
|
object.stubba_class.__method_exists__?(method, false)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'mocha/parameter_matchers/equals'
|
2
|
+
require 'mocha/parameter_matchers/positional_or_keyword_hash'
|
2
3
|
|
3
4
|
module Mocha
|
4
5
|
module ParameterMatchers
|
@@ -16,3 +17,11 @@ end
|
|
16
17
|
class Object
|
17
18
|
include Mocha::ParameterMatchers::InstanceMethods
|
18
19
|
end
|
20
|
+
|
21
|
+
# @private
|
22
|
+
class Hash
|
23
|
+
# @private
|
24
|
+
def to_matcher
|
25
|
+
Mocha::ParameterMatchers::PositionalOrKeywordHash.new(self)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'mocha/configuration'
|
2
|
+
require 'mocha/deprecation'
|
3
|
+
require 'mocha/parameter_matchers/base'
|
4
|
+
|
5
|
+
module Mocha
|
6
|
+
module ParameterMatchers
|
7
|
+
# @private
|
8
|
+
class PositionalOrKeywordHash < Base
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(available_parameters)
|
14
|
+
parameter, is_last_parameter = extract_parameter(available_parameters)
|
15
|
+
return false unless parameter == @value
|
16
|
+
|
17
|
+
if is_last_parameter && !same_type_of_hash?(parameter, @value)
|
18
|
+
return false if Mocha.configuration.strict_keyword_argument_matching?
|
19
|
+
|
20
|
+
deprecation_warning(parameter, @value) if Mocha::RUBY_V27_PLUS
|
21
|
+
end
|
22
|
+
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def mocha_inspect
|
27
|
+
@value.mocha_inspect
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def extract_parameter(available_parameters)
|
33
|
+
[available_parameters.shift, available_parameters.empty?]
|
34
|
+
end
|
35
|
+
|
36
|
+
def same_type_of_hash?(actual, expected)
|
37
|
+
ruby2_keywords_hash?(actual) == ruby2_keywords_hash?(expected)
|
38
|
+
end
|
39
|
+
|
40
|
+
def deprecation_warning(actual, expected)
|
41
|
+
details = "Expected #{hash_type(expected)} (#{expected.mocha_inspect}), but received #{hash_type(actual)} (#{actual.mocha_inspect})."
|
42
|
+
sentence1 = 'These will stop matching when strict keyword argument matching is enabled.'
|
43
|
+
sentence2 = 'See the documentation for Mocha::Configuration#strict_keyword_argument_matching=.'
|
44
|
+
Deprecation.warning([details, sentence1, sentence2].join(' '))
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash_type(hash)
|
48
|
+
ruby2_keywords_hash?(hash) ? 'keyword arguments' : 'positional hash'
|
49
|
+
end
|
50
|
+
|
51
|
+
def ruby2_keywords_hash?(hash)
|
52
|
+
hash.is_a?(Hash) && ::Hash.ruby2_keywords_hash?(hash)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/mocha/ruby_version.rb
CHANGED
data/lib/mocha/stubbed_method.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
+
require 'ruby2_keywords'
|
1
2
|
require 'mocha/ruby_version'
|
2
|
-
require 'mocha/singleton_class'
|
3
3
|
|
4
4
|
module Mocha
|
5
5
|
class StubbedMethod
|
@@ -11,7 +11,7 @@ module Mocha
|
|
11
11
|
@stubbee = stubbee
|
12
12
|
@original_method = nil
|
13
13
|
@original_visibility = nil
|
14
|
-
@method_name =
|
14
|
+
@method_name = method_name.to_sym
|
15
15
|
end
|
16
16
|
|
17
17
|
def stub
|
@@ -21,7 +21,6 @@ module Mocha
|
|
21
21
|
|
22
22
|
def unstub
|
23
23
|
remove_new_method
|
24
|
-
restore_original_method
|
25
24
|
mock.unstub(method_name.to_sym)
|
26
25
|
return if mock.any_expectations?
|
27
26
|
reset_mocha
|
@@ -38,28 +37,16 @@ module Mocha
|
|
38
37
|
def hide_original_method
|
39
38
|
return unless original_method_owner.__method_exists__?(method_name)
|
40
39
|
store_original_method_visibility
|
41
|
-
|
42
|
-
use_prepended_module_for_stub_method
|
43
|
-
else
|
44
|
-
begin
|
45
|
-
store_original_method
|
46
|
-
# rubocop:disable Lint/HandleExceptions
|
47
|
-
rescue NameError
|
48
|
-
# deal with nasties like ActiveRecord::Associations::AssociationProxy
|
49
|
-
end
|
50
|
-
# rubocop:enable Lint/HandleExceptions
|
51
|
-
if stub_method_overwrites_original_method?
|
52
|
-
remove_original_method_from_stubbee
|
53
|
-
end
|
54
|
-
end
|
40
|
+
use_prepended_module_for_stub_method
|
55
41
|
end
|
56
42
|
|
57
43
|
def define_new_method
|
58
44
|
self_in_scope = self
|
59
45
|
method_name_in_scope = method_name
|
60
46
|
stub_method_owner.send(:define_method, method_name) do |*args, &block|
|
61
|
-
self_in_scope.mock.
|
47
|
+
self_in_scope.mock.handle_method_call(method_name_in_scope, args, block)
|
62
48
|
end
|
49
|
+
stub_method_owner.send(:ruby2_keywords, method_name)
|
63
50
|
retain_original_visibility(stub_method_owner)
|
64
51
|
end
|
65
52
|
|
@@ -67,18 +54,6 @@ module Mocha
|
|
67
54
|
stub_method_owner.send(:remove_method, method_name)
|
68
55
|
end
|
69
56
|
|
70
|
-
def store_original_method
|
71
|
-
@original_method = stubbee_method(method_name)
|
72
|
-
end
|
73
|
-
|
74
|
-
def restore_original_method
|
75
|
-
return if use_prepended_module_for_stub_method?
|
76
|
-
if stub_method_overwrites_original_method?
|
77
|
-
original_method_owner.send(:define_method, method_name, method_body(@original_method))
|
78
|
-
end
|
79
|
-
retain_original_visibility(original_method_owner)
|
80
|
-
end
|
81
|
-
|
82
57
|
def matches?(other)
|
83
58
|
return false unless other.class == self.class
|
84
59
|
(stubbee.object_id == other.stubbee.object_id) && (method_name == other.method_name)
|
@@ -101,18 +76,6 @@ module Mocha
|
|
101
76
|
@original_visibility = original_method_owner.__method_visibility__(method_name)
|
102
77
|
end
|
103
78
|
|
104
|
-
def stub_method_overwrites_original_method?
|
105
|
-
@original_method && @original_method.owner == original_method_owner
|
106
|
-
end
|
107
|
-
|
108
|
-
def remove_original_method_from_stubbee
|
109
|
-
original_method_owner.send(:remove_method, method_name)
|
110
|
-
end
|
111
|
-
|
112
|
-
def use_prepended_module_for_stub_method?
|
113
|
-
RUBY_V2_PLUS
|
114
|
-
end
|
115
|
-
|
116
79
|
def use_prepended_module_for_stub_method
|
117
80
|
@stub_method_owner = PrependedModule.new
|
118
81
|
original_method_owner.__send__ :prepend, @stub_method_owner
|
data/lib/mocha/test_unit.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
+
require 'mocha/ruby_version'
|
1
2
|
require 'mocha/integration/test_unit'
|
2
|
-
require 'mocha/deprecation'
|
3
3
|
|
4
4
|
unless Mocha::Integration::TestUnit.activate
|
5
|
-
|
6
|
-
"Test::Unit must be loaded *before* `require 'mocha/test_unit'`."
|
7
|
-
)
|
5
|
+
raise "Test::Unit must be loaded *before* `require 'mocha/test_unit'`."
|
8
6
|
end
|
data/lib/mocha/version.rb
CHANGED
data/lib/mocha.rb
CHANGED
data/mocha.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'mocha'
|
7
7
|
s.version = Mocha::VERSION
|
8
8
|
s.licenses = ['MIT', 'BSD-2-Clause']
|
9
|
-
s.required_ruby_version = '>=
|
9
|
+
s.required_ruby_version = '>= 2.0'
|
10
10
|
|
11
11
|
s.authors = ['James Mead']
|
12
12
|
s.description = 'Mocking and stubbing library with JMock/SchMock syntax, which allows mocking and stubbing of methods on real (non-mock) classes.'
|