mocha 1.16.1 → 2.7.1
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 +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
|