mocha 1.16.1 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -13
- data/.yardopts +1 -2
- data/COPYING.md +2 -2
- data/Gemfile +7 -4
- data/MIT-LICENSE.md +1 -1
- data/README.md +23 -24
- data/RELEASE.md +294 -0
- data/Rakefile +23 -24
- data/lib/mocha/api.rb +30 -71
- data/lib/mocha/backtrace_filter.rb +2 -2
- data/lib/mocha/cardinality.rb +4 -0
- data/lib/mocha/configuration.rb +44 -126
- data/lib/mocha/debug.rb +2 -5
- data/lib/mocha/detection/{mini_test.rb → minitest.rb} +5 -5
- data/lib/mocha/detection/test_unit.rb +2 -2
- data/lib/mocha/expectation.rb +99 -12
- data/lib/mocha/expectation_error_factory.rb +2 -2
- data/lib/mocha/expectation_list.rb +8 -6
- data/lib/mocha/hooks.rb +10 -4
- data/lib/mocha/inspect.rb +15 -4
- data/lib/mocha/integration/{mini_test → minitest}/adapter.rb +21 -6
- data/lib/mocha/integration/{mini_test → minitest}/exception_translation.rb +2 -2
- data/lib/mocha/integration/minitest.rb +28 -0
- data/lib/mocha/integration/test_unit/adapter.rb +9 -4
- data/lib/mocha/integration/test_unit.rb +10 -31
- data/lib/mocha/invocation.rb +2 -15
- data/lib/mocha/minitest.rb +3 -6
- data/lib/mocha/mock.rb +45 -18
- data/lib/mocha/mockery.rb +13 -9
- data/lib/mocha/names.rb +1 -1
- data/lib/mocha/object_methods.rb +2 -2
- data/lib/mocha/parameter_matchers/base.rb +4 -9
- data/lib/mocha/parameter_matchers/equivalent_uri.rb +1 -2
- data/lib/mocha/parameter_matchers/has_entries.rb +7 -2
- data/lib/mocha/parameter_matchers/includes.rb +3 -3
- data/lib/mocha/parameter_matchers/instance_methods.rb +10 -2
- data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +66 -0
- data/lib/mocha/parameter_matchers/responds_with.rb +32 -5
- data/lib/mocha/parameters_matcher.rb +10 -6
- data/lib/mocha/ruby_version.rb +2 -9
- data/lib/mocha/stubbed_method.rb +3 -39
- data/lib/mocha/test_unit.rb +1 -4
- data/lib/mocha/version.rb +1 -1
- data/mocha.gemspec +11 -1
- metadata +31 -31
- 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/mini_test.rb +0 -56
- 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_186_and_above.rb +0 -63
- data/lib/mocha/integration.rb +0 -11
- data/lib/mocha/setup.rb +0 -14
- data/yard-templates/default/layout/html/google_analytics.erb +0 -8
- data/yard-templates/default/layout/html/setup.rb +0 -5
data/Rakefile
CHANGED
@@ -5,9 +5,14 @@ end
|
|
5
5
|
require 'bundler/setup'
|
6
6
|
|
7
7
|
require 'rake/testtask'
|
8
|
+
begin
|
9
|
+
# Only available with default Gemfile and in Ruby >= v2.2
|
10
|
+
require 'rubocop/rake_task'
|
11
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
12
|
+
end
|
8
13
|
|
9
|
-
desc 'Run all tests'
|
10
|
-
task 'default' => ['test', 'test:performance']
|
14
|
+
desc 'Run all linters and tests'
|
15
|
+
task 'default' => ['lint', 'test', 'test:performance']
|
11
16
|
|
12
17
|
desc 'Run tests'
|
13
18
|
task 'test' do
|
@@ -37,10 +42,10 @@ namespace 'test' do # rubocop:disable Metrics/BlockLength
|
|
37
42
|
end
|
38
43
|
|
39
44
|
namespace 'integration' do
|
40
|
-
desc 'Run
|
45
|
+
desc 'Run Minitest integration tests (intended to be run in its own process)'
|
41
46
|
Rake::TestTask.new('minitest') do |t|
|
42
47
|
t.libs << 'test'
|
43
|
-
t.test_files = FileList['test/integration/
|
48
|
+
t.test_files = FileList['test/integration/minitest_test.rb']
|
44
49
|
t.verbose = true
|
45
50
|
t.warning = true
|
46
51
|
end
|
@@ -76,37 +81,37 @@ namespace 'test' do # rubocop:disable Metrics/BlockLength
|
|
76
81
|
end
|
77
82
|
end
|
78
83
|
|
79
|
-
|
80
|
-
|
81
|
-
if RUBY_VERSION >= '2.2.0' && (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby') && ENV['MOCHA_RUN_INTEGRATION_TESTS'].nil?
|
84
|
+
task 'lint' do
|
85
|
+
if defined?(RuboCop::RakeTask)
|
82
86
|
RuboCop::RakeTask.new
|
83
|
-
|
87
|
+
Rake::Task['rubocop'].invoke
|
88
|
+
else
|
89
|
+
puts 'RuboCop not available - skipping linting'
|
84
90
|
end
|
85
|
-
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
86
91
|
end
|
87
92
|
|
88
93
|
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
89
94
|
def benchmark_test_case(klass, iterations)
|
90
95
|
require 'benchmark'
|
91
|
-
require 'mocha/detection/
|
96
|
+
require 'mocha/detection/minitest'
|
92
97
|
|
93
|
-
if defined?(
|
94
|
-
minitest_version = Gem::Version.new(Mocha::Detection::
|
98
|
+
if defined?(Minitest)
|
99
|
+
minitest_version = Gem::Version.new(Mocha::Detection::Minitest.version)
|
95
100
|
if Gem::Requirement.new('>= 5.0.0').satisfied_by?(minitest_version)
|
96
101
|
Minitest.seed = 1
|
97
|
-
result = Benchmark.realtime { iterations.times { |_i| klass.run(
|
98
|
-
|
102
|
+
result = Benchmark.realtime { iterations.times { |_i| klass.run(Minitest::CompositeReporter.new) } }
|
103
|
+
Minitest::Runnable.runnables.delete(klass)
|
99
104
|
result
|
100
105
|
else
|
101
|
-
|
102
|
-
Benchmark.realtime { iterations.times { |_i|
|
106
|
+
Minitest::Unit.output = StringIO.new
|
107
|
+
Benchmark.realtime { iterations.times { |_i| Minitest::Unit.new.run([klass]) } }
|
103
108
|
end
|
104
109
|
else
|
105
110
|
load 'test/unit/ui/console/testrunner.rb' unless defined?(Test::Unit::UI::Console::TestRunner)
|
106
111
|
unless @silent_option
|
107
112
|
begin
|
108
113
|
load 'test/unit/ui/console/outputlevel.rb' unless defined?(Test::Unit::UI::Console::OutputLevel::SILENT)
|
109
|
-
@silent_option = { :
|
114
|
+
@silent_option = { output_level: Test::Unit::UI::Console::OutputLevel::SILENT }
|
110
115
|
rescue LoadError
|
111
116
|
@silent_option = Test::Unit::UI::SILENT
|
112
117
|
end
|
@@ -124,14 +129,8 @@ if ENV['MOCHA_GENERATE_DOCS']
|
|
124
129
|
`rm -rf ./docs`
|
125
130
|
end
|
126
131
|
|
127
|
-
task 'docs_environment' do
|
128
|
-
unless ENV['GOOGLE_ANALYTICS_WEB_PROPERTY_ID']
|
129
|
-
puts "\nWarning: GOOGLE_ANALYTICS_WEB_PROPERTY_ID was not defined\n\n"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
132
|
desc 'Generate documentation'
|
134
|
-
YARD::Rake::YardocTask.new('yardoc'
|
133
|
+
YARD::Rake::YardocTask.new('yardoc') do |task|
|
135
134
|
task.options = ['--title', "Mocha #{Mocha::VERSION}", '--fail-on-warning']
|
136
135
|
end
|
137
136
|
|
data/lib/mocha/api.rb
CHANGED
@@ -7,7 +7,7 @@ require 'mocha/object_methods'
|
|
7
7
|
require 'mocha/class_methods'
|
8
8
|
|
9
9
|
module Mocha
|
10
|
-
# Methods added to +Test::Unit::TestCase+, +
|
10
|
+
# Methods added to +Test::Unit::TestCase+, +Minitest::Unit::TestCase+ or equivalent.
|
11
11
|
# The mock creation methods are {#mock}, {#stub} and {#stub_everything}, all of which return a #{Mock}
|
12
12
|
# which can be further modified by {Mock#responds_like} and {Mock#responds_like_instance_of} methods,
|
13
13
|
# both of which return a {Mock}, too, and can therefore, be chained to the original creation methods.
|
@@ -52,7 +52,6 @@ module Mocha
|
|
52
52
|
#
|
53
53
|
# @overload def mock(name)
|
54
54
|
# @param [String, Symbol] name identifies mock object in error messages.
|
55
|
-
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that expected the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
56
55
|
# @overload def mock(expected_methods_vs_return_values = {})
|
57
56
|
# @param [Hash] expected_methods_vs_return_values expected method name symbols as keys and corresponding return values as values - these expectations are setup as if {Mock#expects} were called multiple times.
|
58
57
|
# @overload def mock(name, expected_methods_vs_return_values = {})
|
@@ -61,32 +60,14 @@ module Mocha
|
|
61
60
|
#
|
62
61
|
# @example Using expected_methods_vs_return_values Hash to setup expectations.
|
63
62
|
# def test_motor_starts_and_stops
|
64
|
-
# motor = mock('motor', :
|
63
|
+
# motor = mock('motor', start: true, stop: true)
|
65
64
|
# assert motor.start
|
66
65
|
# assert motor.stop
|
67
66
|
# # an error will be raised unless both Motor#start and Motor#stop have been called
|
68
67
|
# end
|
69
68
|
#
|
70
|
-
def mock(*arguments)
|
71
|
-
if
|
72
|
-
if arguments.first.is_a?(Symbol)
|
73
|
-
method_name = arguments[0]
|
74
|
-
Deprecation.warning(
|
75
|
-
"Explicitly include `#{method_name}` in Hash of expected methods vs return values,",
|
76
|
-
" e.g. `mock(:#{method_name} => nil)`."
|
77
|
-
)
|
78
|
-
if arguments[1]
|
79
|
-
Deprecation.warning(
|
80
|
-
"In this case the 2nd argument for `mock(:##{method_name}, ...)` is ignored,",
|
81
|
-
' but in the future a Hash of expected methods vs return values will be respected.'
|
82
|
-
)
|
83
|
-
end
|
84
|
-
elsif arguments.first.is_a?(String)
|
85
|
-
name = arguments.shift
|
86
|
-
end
|
87
|
-
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
88
|
-
name = arguments.shift
|
89
|
-
end
|
69
|
+
def mock(*arguments)
|
70
|
+
name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
90
71
|
expectations = arguments.shift || {}
|
91
72
|
mock = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
92
73
|
mock.expects(expectations)
|
@@ -99,46 +80,26 @@ module Mocha
|
|
99
80
|
#
|
100
81
|
# @overload def stub(name)
|
101
82
|
# @param [String, Symbol] name identifies mock object in error messages.
|
102
|
-
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that stubbed the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
103
83
|
# @overload def stub(stubbed_methods_vs_return_values = {})
|
104
84
|
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
|
105
85
|
# @overload def stub(name, stubbed_methods_vs_return_values = {})
|
106
86
|
# @param [String, Symbol] name identifies mock object in error messages.
|
87
|
+
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
|
107
88
|
#
|
108
89
|
# @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
|
109
90
|
# def test_motor_starts_and_stops
|
110
|
-
# motor = stub('motor', :
|
91
|
+
# motor = stub('motor', start: true, stop: true)
|
111
92
|
# assert motor.start
|
112
93
|
# assert motor.stop
|
113
94
|
# # an error will not be raised even if either Motor#start or Motor#stop has not been called
|
114
95
|
# end
|
115
|
-
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
116
96
|
def stub(*arguments)
|
117
|
-
if
|
118
|
-
if arguments.first.is_a?(Symbol)
|
119
|
-
method_name = arguments[0]
|
120
|
-
Deprecation.warning(
|
121
|
-
"Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
|
122
|
-
" e.g. `stub(:#{method_name} => nil)`."
|
123
|
-
)
|
124
|
-
if arguments[1]
|
125
|
-
Deprecation.warning(
|
126
|
-
"In this case the 2nd argument for `stub(:##{method_name}, ...)` is ignored,",
|
127
|
-
' but in the future a Hash of stubbed methods vs return values will be respected.'
|
128
|
-
)
|
129
|
-
end
|
130
|
-
elsif arguments.first.is_a?(String)
|
131
|
-
name = arguments.shift
|
132
|
-
end
|
133
|
-
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
134
|
-
name = arguments.shift
|
135
|
-
end
|
97
|
+
name = arguments.shift.to_s if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
136
98
|
expectations = arguments.shift || {}
|
137
99
|
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
138
100
|
stub.stubs(expectations)
|
139
101
|
stub
|
140
102
|
end
|
141
|
-
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
142
103
|
|
143
104
|
# Builds a mock object that accepts calls to any method. By default it will return +nil+ for any method call.
|
144
105
|
#
|
@@ -146,7 +107,6 @@ module Mocha
|
|
146
107
|
#
|
147
108
|
# @overload def stub_everything(name)
|
148
109
|
# @param [String, Symbol] name identifies mock object in error messages.
|
149
|
-
# @note Prior to v1.10.0 when +name+ was a +Symbol+, this method returned an unnamed +Mock+ that stubbed the method identified by +name+. This was undocumented behaviour and it will be removed in the future, but for the moment it can be reinstated using {Configuration#reinstate_undocumented_behaviour_from_v1_9=}.
|
150
110
|
# @overload def stub_everything(stubbed_methods_vs_return_values = {})
|
151
111
|
# @param [Hash] stubbed_methods_vs_return_values stubbed method name symbols as keys and corresponding return values as values - these stubbed methods are setup as if {Mock#stubs} were called multiple times.
|
152
112
|
# @overload def stub_everything(name, stubbed_methods_vs_return_values = {})
|
@@ -155,44 +115,27 @@ module Mocha
|
|
155
115
|
#
|
156
116
|
# @example Ignore invocations of irrelevant methods.
|
157
117
|
# def test_motor_stops
|
158
|
-
# motor = stub_everything('motor', :
|
118
|
+
# motor = stub_everything('motor', stop: true)
|
159
119
|
# assert_nil motor.irrelevant_method_1 # => no error raised
|
160
120
|
# assert_nil motor.irrelevant_method_2 # => no error raised
|
161
121
|
# assert motor.stop
|
162
122
|
# end
|
163
|
-
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
164
123
|
def stub_everything(*arguments)
|
165
|
-
if
|
166
|
-
if arguments.first.is_a?(Symbol)
|
167
|
-
method_name = arguments[0]
|
168
|
-
Deprecation.warning(
|
169
|
-
"Explicitly include `#{method_name}` in Hash of stubbed methods vs return values,",
|
170
|
-
" e.g. `stub_everything(:#{method_name} => nil)`."
|
171
|
-
)
|
172
|
-
if arguments[1]
|
173
|
-
Deprecation.warning(
|
174
|
-
"In this case the 2nd argument for `stub_everything(:##{method_name}, ...)` is ignored,",
|
175
|
-
' but in the future a Hash of stubbed methods vs return values will be respected.'
|
176
|
-
)
|
177
|
-
end
|
178
|
-
elsif arguments.first.is_a?(String)
|
179
|
-
name = arguments.shift
|
180
|
-
end
|
181
|
-
elsif arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
182
|
-
name = arguments.shift
|
183
|
-
end
|
124
|
+
name = arguments.shift if arguments.first.is_a?(String) || arguments.first.is_a?(Symbol)
|
184
125
|
expectations = arguments.shift || {}
|
185
126
|
stub = name ? Mockery.instance.named_mock(name) : Mockery.instance.unnamed_mock
|
186
127
|
stub.stub_everything
|
187
128
|
stub.stubs(expectations)
|
188
129
|
stub
|
189
130
|
end
|
190
|
-
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
191
131
|
|
192
132
|
# Builds a new sequence which can be used to constrain the order in which expectations can occur.
|
193
133
|
#
|
194
|
-
# Specify that an expected invocation must occur within a named {Sequence} by
|
134
|
+
# Specify that an expected invocation must occur within a named {Sequence} by calling {Expectation#in_sequence}
|
135
|
+
# on each expectation or by passing a block within which all expectations should be constrained by the {Sequence}.
|
195
136
|
#
|
137
|
+
# @param [String] name name of sequence
|
138
|
+
# @yield optional block within which expectations should be constrained by the sequence
|
196
139
|
# @return [Sequence] a new sequence
|
197
140
|
#
|
198
141
|
# @see Expectation#in_sequence
|
@@ -216,8 +159,23 @@ module Mocha
|
|
216
159
|
#
|
217
160
|
# task_one.execute
|
218
161
|
# task_two.execute
|
162
|
+
#
|
163
|
+
# @example Ensure methods on egg are invoked in the correct order using a block.
|
164
|
+
# egg = mock('egg')
|
165
|
+
# sequence('breakfast') do
|
166
|
+
# egg.expects(:crack)
|
167
|
+
# egg.expects(:fry)
|
168
|
+
# egg.expects(:eat)
|
169
|
+
# end
|
219
170
|
def sequence(name)
|
220
|
-
Sequence.new(name)
|
171
|
+
Sequence.new(name).tap do |seq|
|
172
|
+
Mockery.instance.sequences.push(seq)
|
173
|
+
begin
|
174
|
+
yield if block_given?
|
175
|
+
ensure
|
176
|
+
Mockery.instance.sequences.pop
|
177
|
+
end
|
178
|
+
end
|
221
179
|
end
|
222
180
|
|
223
181
|
# Builds a new state machine which can be used to constrain the order in which expectations can occur.
|
@@ -230,6 +188,7 @@ module Mocha
|
|
230
188
|
#
|
231
189
|
# A test can contain multiple state machines.
|
232
190
|
#
|
191
|
+
# @param [String] name name of state machine
|
233
192
|
# @return [StateMachine] a new state machine
|
234
193
|
#
|
235
194
|
# @see Expectation#then
|
@@ -3,11 +3,11 @@ module Mocha
|
|
3
3
|
LIB_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..')) + File::SEPARATOR
|
4
4
|
|
5
5
|
def initialize(lib_directory = LIB_DIRECTORY)
|
6
|
-
@
|
6
|
+
@lib_directory = lib_directory
|
7
7
|
end
|
8
8
|
|
9
9
|
def filtered(backtrace)
|
10
|
-
backtrace.reject { |location|
|
10
|
+
backtrace.reject { |location| File.expand_path(location).start_with?(@lib_directory) }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
data/lib/mocha/cardinality.rb
CHANGED
data/lib/mocha/configuration.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'mocha/ruby_version'
|
2
|
+
require 'mocha/deprecation'
|
3
|
+
|
1
4
|
module Mocha
|
2
5
|
# Allows setting of configuration options. See {Configuration} for the available options.
|
3
6
|
#
|
@@ -37,13 +40,13 @@ module Mocha
|
|
37
40
|
class Configuration
|
38
41
|
# @private
|
39
42
|
DEFAULTS = {
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
43
|
+
stubbing_method_unnecessarily: :allow,
|
44
|
+
stubbing_method_on_non_mock_object: :allow,
|
45
|
+
stubbing_non_existent_method: :allow,
|
46
|
+
stubbing_non_public_method: :allow,
|
47
|
+
stubbing_method_on_nil: :prevent,
|
48
|
+
display_matching_invocations_on_failure: false,
|
49
|
+
strict_keyword_argument_matching: false
|
47
50
|
}.freeze
|
48
51
|
|
49
52
|
attr_reader :options
|
@@ -204,8 +207,14 @@ module Mocha
|
|
204
207
|
# When +value+ is +:prevent+, raise a {StubbingError}. This is the default.
|
205
208
|
#
|
206
209
|
# @param [Symbol] value one of +:allow+, +:warn+, +:prevent+.
|
210
|
+
# @deprecated This method is deprecated and will be removed in a future release. +nil+ is frozen in Ruby >= v2.2 and Mocha will be dropping support for Ruby v2.1. At that point it won't be possible to stub methods on +nil+ any more.
|
207
211
|
#
|
208
212
|
def stubbing_method_on_nil=(value)
|
213
|
+
Deprecation.warning([
|
214
|
+
'`Mocha::Configuration#stubbing_method_on_nil=` is deprecated and will be removed in a future release.',
|
215
|
+
'`nil` is frozen in Ruby >= v2.2 and Mocha will be dropping support for Ruby v2.1.',
|
216
|
+
"At that point it won't be possible to stub methods on `nil` any more."
|
217
|
+
].join(' '))
|
209
218
|
@options[:stubbing_method_on_nil] = value
|
210
219
|
end
|
211
220
|
|
@@ -248,145 +257,54 @@ module Mocha
|
|
248
257
|
@options[:display_matching_invocations_on_failure]
|
249
258
|
end
|
250
259
|
|
251
|
-
#
|
252
|
-
#
|
253
|
-
# Previously when {API#mock}, {API#stub}, or {API#stub_everything} were called with the first argument being a symbol, they built an *unnamed* mock object *and* expected or stubbed the method identified by the symbol argument; subsequent arguments were ignored.
|
254
|
-
# Now these methods build a *named* mock with the name specified by the symbol argument; *no* methods are expected or stubbed and subsequent arguments *are* taken into account.
|
260
|
+
# Perform strict keyword argument comparison. Only supported in Ruby >= v2.7.
|
255
261
|
#
|
256
|
-
#
|
257
|
-
# Now a +LocalJumpError+ is raised.
|
262
|
+
# When this option is set to +false+ a positional +Hash+ and a set of keyword arguments are treated the same during comparison, which can lead to misleading passing tests in Ruby >= v3.0 (see examples below). However, a deprecation warning will be displayed if a positional +Hash+ matches a set of keyword arguments or vice versa. This is because {#strict_keyword_argument_matching=} will default to +true+ in the future.
|
258
263
|
#
|
259
|
-
#
|
264
|
+
# For more details on keyword arguments in Ruby v3, refer to {https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0 this article}.
|
260
265
|
#
|
261
|
-
#
|
262
|
-
# @deprecated Fix deprecation warnings caused by reliance on v1.9 behaviour and remove calls to this method.
|
266
|
+
# Note that +Hash+-related matchers such as {ParameterMatchers#has_value} or {ParameterMatchers#has_key} will still treat a positional +Hash+ and a set of keyword arguments the same, so misleading passing tests are still possible when they are used.
|
263
267
|
#
|
264
|
-
#
|
265
|
-
# Mocha.configure do |c|
|
266
|
-
# c.reinstate_undocumented_behaviour_from_v1_9 = true
|
267
|
-
# end
|
268
|
+
# This configuration option is +false+ by default to enable gradual adoption, but will be +true+ by default in the future.
|
268
269
|
#
|
269
|
-
#
|
270
|
-
# foo.inspect # => #<Mock>
|
270
|
+
# @param [Boolean] value +true+ to enable strict keyword argument matching; +false+ by default.
|
271
271
|
#
|
272
|
-
#
|
273
|
-
# unsatisfied expectations:
|
274
|
-
# - expected exactly once, invoked never: #<Mock>.foo
|
272
|
+
# @example Loose keyword argument matching (default)
|
275
273
|
#
|
276
|
-
#
|
277
|
-
#
|
278
|
-
# c.reinstate_undocumented_behaviour_from_v1_9 = true
|
274
|
+
# class Example
|
275
|
+
# def foo(a, bar:); end
|
279
276
|
# end
|
280
277
|
#
|
281
|
-
#
|
282
|
-
# foo.
|
283
|
-
# foo
|
278
|
+
# example = Example.new
|
279
|
+
# example.expects(:foo).with('a', bar: 'b')
|
280
|
+
# example.foo('a', { bar: 'b' })
|
281
|
+
# # This passes the test, but would result in an ArgumentError in practice
|
284
282
|
#
|
285
|
-
# @example
|
286
|
-
# foo = mock('foo')
|
287
|
-
# foo.stubs(:my_method).yields(1, 2)
|
288
|
-
# foo.my_method # => raises LocalJumpError when no block is supplied
|
283
|
+
# @example Strict keyword argument matching
|
289
284
|
#
|
290
285
|
# Mocha.configure do |c|
|
291
|
-
# c.
|
286
|
+
# c.strict_keyword_argument_matching = true
|
292
287
|
# end
|
293
288
|
#
|
294
|
-
#
|
295
|
-
#
|
296
|
-
#
|
297
|
-
#
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
sentence1 = 'Configuration#reinstate_undocumented_behaviour_from_v1_9= is unnecessarily being set to false, because this is now the default value.'
|
306
|
-
sentence2 = 'Configuration#reinstate_undocumented_behaviour_from_v1_9= will be removed in the future, so you should avoid calling it.'
|
307
|
-
Deprecation.warning([sentence1, sentence2].join(' '))
|
308
|
-
end
|
309
|
-
@options[:reinstate_undocumented_behaviour_from_v1_9] = value
|
289
|
+
# class Example
|
290
|
+
# def foo(a, bar:); end
|
291
|
+
# end
|
292
|
+
#
|
293
|
+
# example = Example.new
|
294
|
+
# example.expects(:foo).with('a', bar: 'b')
|
295
|
+
# example.foo('a', { bar: 'b' })
|
296
|
+
# # This now fails as expected
|
297
|
+
def strict_keyword_argument_matching=(value)
|
298
|
+
raise 'Strict keyword argument matching requires Ruby 2.7 and above.' unless Mocha::RUBY_V27_PLUS
|
299
|
+
@options[:strict_keyword_argument_matching] = value
|
310
300
|
end
|
311
301
|
|
312
302
|
# @private
|
313
|
-
def
|
314
|
-
@options[:
|
303
|
+
def strict_keyword_argument_matching?
|
304
|
+
@options[:strict_keyword_argument_matching]
|
315
305
|
end
|
316
306
|
|
317
307
|
class << self
|
318
|
-
# Allow the specified +action+.
|
319
|
-
#
|
320
|
-
# @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
|
321
|
-
# @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
|
322
|
-
# @deprecated If a block is supplied, call {.override} with a +Hash+ containing an entry with the +action+ as the key and +:allow+ as the value. If no block is supplied, call the appropriate +action+ writer method with +value+ set to +:allow+ via {Mocha.configure}. The writer method will be the one of the following corresponding to the +action+:
|
323
|
-
# * {#stubbing_method_unnecessarily=}
|
324
|
-
# * {#stubbing_method_on_non_mock_object=}
|
325
|
-
# * {#stubbing_non_existent_method=}
|
326
|
-
# * {#stubbing_non_public_method=}
|
327
|
-
# * {#stubbing_method_on_nil=}
|
328
|
-
def allow(action, &block)
|
329
|
-
if block_given?
|
330
|
-
Deprecation.warning("Use Mocha::Configuration.override(#{action}: :allow) with the same block")
|
331
|
-
else
|
332
|
-
Deprecation.warning("Use Mocha.configure { |c| c.#{action} = :allow }")
|
333
|
-
end
|
334
|
-
change_config action, :allow, &block
|
335
|
-
end
|
336
|
-
|
337
|
-
# @private
|
338
|
-
def allow?(action)
|
339
|
-
configuration.allow?(action)
|
340
|
-
end
|
341
|
-
|
342
|
-
# Warn if the specified +action+ is attempted.
|
343
|
-
#
|
344
|
-
# @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
|
345
|
-
# @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
|
346
|
-
# @deprecated If a block is supplied, call {.override} with a +Hash+ containing an entry with the +action+ as the key and +:warn+ as the value. If no block is supplied, call the appropriate +action+ writer method with +value+ set to +:warn+ via {Mocha.configure}. The writer method will be the one of the following corresponding to the +action+:
|
347
|
-
# * {#stubbing_method_unnecessarily=}
|
348
|
-
# * {#stubbing_method_on_non_mock_object=}
|
349
|
-
# * {#stubbing_non_existent_method=}
|
350
|
-
# * {#stubbing_non_public_method=}
|
351
|
-
# * {#stubbing_method_on_nil=}
|
352
|
-
def warn_when(action, &block)
|
353
|
-
if block_given?
|
354
|
-
Deprecation.warning("Use Mocha::Configuration.override(#{action}: :warn) with the same block")
|
355
|
-
else
|
356
|
-
Deprecation.warning("Use Mocha.configure { |c| c.#{action} = :warn }")
|
357
|
-
end
|
358
|
-
change_config action, :warn, &block
|
359
|
-
end
|
360
|
-
|
361
|
-
# @private
|
362
|
-
def warn_when?(action)
|
363
|
-
configuration.warn_when?(action)
|
364
|
-
end
|
365
|
-
|
366
|
-
# Raise a {StubbingError} if the specified +action+ is attempted.
|
367
|
-
#
|
368
|
-
# @param [Symbol] action one of +:stubbing_method_unnecessarily+, +:stubbing_method_on_non_mock_object+, +:stubbing_non_existent_method+, +:stubbing_non_public_method+, +:stubbing_method_on_nil+.
|
369
|
-
# @yield optional block during which the configuration change will be changed before being returned to its original value at the end of the block.
|
370
|
-
# @deprecated If a block is supplied, call {.override} with a +Hash+ containing an entry with the +action+ as the key and +:prevent+ as the value. If no block is supplied, call the appropriate +action+ writer method with +value+ set to +:prevent+ via {Mocha.configure}. The writer method will be the one of the following corresponding to the +action+:
|
371
|
-
# * {#stubbing_method_unnecessarily=}
|
372
|
-
# * {#stubbing_method_on_non_mock_object=}
|
373
|
-
# * {#stubbing_non_existent_method=}
|
374
|
-
# * {#stubbing_non_public_method=}
|
375
|
-
# * {#stubbing_method_on_nil=}
|
376
|
-
def prevent(action, &block)
|
377
|
-
if block_given?
|
378
|
-
Deprecation.warning("Use Mocha::Configuration.override(#{action}: :prevent) with the same block")
|
379
|
-
else
|
380
|
-
Deprecation.warning("Use Mocha.configure { |c| c.#{action} = :prevent }")
|
381
|
-
end
|
382
|
-
change_config action, :prevent, &block
|
383
|
-
end
|
384
|
-
|
385
|
-
# @private
|
386
|
-
def prevent?(action)
|
387
|
-
configuration.prevent?(action)
|
388
|
-
end
|
389
|
-
|
390
308
|
# @private
|
391
309
|
def reset_configuration
|
392
310
|
@configuration = nil
|
data/lib/mocha/debug.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
module Mocha
|
2
2
|
module Debug
|
3
|
-
OPTIONS = (ENV['MOCHA_OPTIONS'] || '').split(',').
|
4
|
-
hash[key] = true
|
5
|
-
hash
|
6
|
-
end.freeze
|
3
|
+
OPTIONS = (ENV['MOCHA_OPTIONS'] || '').split(',').freeze
|
7
4
|
|
8
5
|
def self.puts(message)
|
9
|
-
warn(message) if OPTIONS
|
6
|
+
warn(message) if OPTIONS.include?('debug')
|
10
7
|
end
|
11
8
|
end
|
12
9
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module Mocha
|
2
2
|
module Detection
|
3
|
-
module
|
3
|
+
module Minitest
|
4
4
|
def self.testcase
|
5
5
|
if defined?(::Minitest::Test)
|
6
6
|
::Minitest::Test
|
7
|
-
elsif defined?(::
|
8
|
-
::
|
7
|
+
elsif defined?(::Minitest::Unit::TestCase)
|
8
|
+
::Minitest::Unit::TestCase
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.version
|
13
|
-
if defined?(::
|
14
|
-
::
|
13
|
+
if defined?(::Minitest::Unit::VERSION)
|
14
|
+
::Minitest::Unit::VERSION
|
15
15
|
elsif defined?(::Minitest::VERSION)
|
16
16
|
::Minitest::VERSION
|
17
17
|
else
|
@@ -3,8 +3,8 @@ module Mocha
|
|
3
3
|
module TestUnit
|
4
4
|
def self.testcase
|
5
5
|
if defined?(::Test::Unit::TestCase) &&
|
6
|
-
!(defined?(::
|
7
|
-
!(defined?(::
|
6
|
+
!(defined?(::Minitest::Unit::TestCase) && (::Test::Unit::TestCase < ::Minitest::Unit::TestCase)) &&
|
7
|
+
!(defined?(::Minitest::Spec) && (::Test::Unit::TestCase < ::Minitest::Spec))
|
8
8
|
::Test::Unit::TestCase
|
9
9
|
end
|
10
10
|
end
|