mocha 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.yardopts +1 -1
- data/README.md +10 -10
- data/RELEASE.md +28 -0
- data/Rakefile +9 -9
- data/lib/mocha/api.rb +25 -6
- 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 +8 -2
- data/lib/mocha/expectation_error_factory.rb +2 -2
- data/lib/mocha/expectation_list.rb +7 -3
- data/lib/mocha/hooks.rb +10 -4
- data/lib/mocha/integration/{mini_test → minitest}/adapter.rb +20 -5
- 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 +5 -0
- data/lib/mocha/minitest.rb +3 -3
- data/lib/mocha/mock.rb +16 -10
- data/lib/mocha/mockery.rb +8 -4
- data/lib/mocha/object_methods.rb +2 -2
- data/lib/mocha/parameter_matchers/base.rb +4 -4
- data/lib/mocha/parameter_matchers/includes.rb +3 -3
- data/lib/mocha/parameter_matchers/positional_or_keyword_hash.rb +2 -1
- data/lib/mocha/parameter_matchers/responds_with.rb +32 -5
- data/lib/mocha/version.rb +1 -1
- data/mocha.gemspec +1 -1
- metadata +7 -7
- data/lib/mocha/integration/mini_test.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d39bbef9363c1fb12001142111cd1e324a7c304100f456d0c723e9d839a15de4
|
4
|
+
data.tar.gz: 9a91ce33d3fcacd82f4f4461da86042f66e9c0e0efdba61fbaf588aaddb0ce91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0662556bb9f093c581bdea78f4484a0d8472dd63a7ee4589ebcdd4564628780e1cc68c32e9a4ae334d08ebe4bab75a9b9aeffe177a560e2e5424d9ff5349f4c7
|
7
|
+
data.tar.gz: ecabbed8691ddaea029cb0272705c1701c5b2815bfca4236baa559ea6f53eef3e8f650be861b81a43b3e9dff59edcca8a195ccaea7e2ef31f0990e8873753ed4
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
inherit_from: .rubocop_todo.yml
|
2
2
|
|
3
3
|
AllCops:
|
4
|
-
TargetRubyVersion: 2.2 # closest to required_ruby_version of '>= 2.
|
4
|
+
TargetRubyVersion: 2.2 # closest to required_ruby_version of '>= 2.1'
|
5
5
|
|
6
6
|
# Even the reference in the documentation suggests that you should prefer
|
7
7
|
# `alias_method` vs `alias`, so I don't understand why that isn't the default.
|
data/.yardopts
CHANGED
@@ -16,7 +16,7 @@ lib/mocha/expectation_error.rb
|
|
16
16
|
lib/mocha/stubbing_error.rb
|
17
17
|
lib/mocha/unexpected_invocation.rb
|
18
18
|
lib/mocha/integration/test_unit/adapter.rb
|
19
|
-
lib/mocha/integration/
|
19
|
+
lib/mocha/integration/minitest/adapter.rb
|
20
20
|
-
|
21
21
|
RELEASE.md
|
22
22
|
COPYING.md
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
* A Ruby library for [mocking](http://xunitpatterns.com/Mock%20Object.html) and [stubbing](http://xunitpatterns.com/Test%20Stub.html) - but deliberately not (yet) [faking](http://xunitpatterns.com/Fake%20Object.html) or [spying](http://xunitpatterns.com/Test%20Spy.html).
|
6
6
|
* A unified, simple and readable syntax for both full & partial mocking.
|
7
|
-
* Built-in support for
|
7
|
+
* Built-in support for Minitest and Test::Unit.
|
8
8
|
* Supported by many other test frameworks.
|
9
9
|
|
10
10
|
### Intended Usage
|
@@ -18,7 +18,7 @@ Install the latest version of the gem with the following command...
|
|
18
18
|
|
19
19
|
$ gem install mocha
|
20
20
|
|
21
|
-
Note: If you are intending to use Mocha with Test::Unit or
|
21
|
+
Note: If you are intending to use Mocha with Test::Unit or Minitest, you should only setup Mocha *after* loading the relevant test library...
|
22
22
|
|
23
23
|
##### Test::Unit
|
24
24
|
|
@@ -29,12 +29,12 @@ require 'test/unit'
|
|
29
29
|
require 'mocha/test_unit'
|
30
30
|
```
|
31
31
|
|
32
|
-
#####
|
32
|
+
##### Minitest
|
33
33
|
|
34
34
|
```ruby
|
35
35
|
require 'rubygems'
|
36
36
|
gem 'mocha'
|
37
|
-
require 'minitest/
|
37
|
+
require 'minitest/autorun'
|
38
38
|
require 'mocha/minitest'
|
39
39
|
```
|
40
40
|
|
@@ -53,14 +53,14 @@ require 'test/unit'
|
|
53
53
|
require 'mocha/test_unit'
|
54
54
|
```
|
55
55
|
|
56
|
-
#####
|
56
|
+
##### Minitest
|
57
57
|
|
58
58
|
```ruby
|
59
59
|
# Gemfile
|
60
60
|
gem 'mocha'
|
61
61
|
|
62
62
|
# Elsewhere after Bundler has loaded gems e.g. after `require 'bundler/setup'`
|
63
|
-
require 'minitest/
|
63
|
+
require 'minitest/autorun'
|
64
64
|
require 'mocha/minitest'
|
65
65
|
```
|
66
66
|
|
@@ -103,9 +103,9 @@ end
|
|
103
103
|
|
104
104
|
If you're loading Mocha using Bundler within a Rails application, you should setup Mocha manually e.g. at the bottom of your `test_helper.rb`.
|
105
105
|
|
106
|
-
#####
|
106
|
+
##### Minitest
|
107
107
|
|
108
|
-
Note that since Rails v4 (at least), `ActiveSupport::TestCase` has inherited from `Minitest::Test` or its earlier equivalents. Thus unless you are *explicitly* using Test::Unit, you are likely to be using
|
108
|
+
Note that since Rails v4 (at least), `ActiveSupport::TestCase` has inherited from `Minitest::Test` or its earlier equivalents. Thus unless you are *explicitly* using Test::Unit, you are likely to be using Minitest.
|
109
109
|
|
110
110
|
```ruby
|
111
111
|
# Gemfile in Rails app
|
@@ -151,7 +151,7 @@ class MiscExampleTest < Test::Unit::TestCase
|
|
151
151
|
end
|
152
152
|
|
153
153
|
def test_stubbing_instance_methods_on_real_objects
|
154
|
-
prices = [stub(:
|
154
|
+
prices = [stub(pence: 1000), stub(pence: 2000)]
|
155
155
|
product = Product.new
|
156
156
|
product.stubs(:prices).returns(prices)
|
157
157
|
assert_equal [1000, 2000], product.prices.collect {|p| p.pence}
|
@@ -170,7 +170,7 @@ class MiscExampleTest < Test::Unit::TestCase
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def test_shortcuts
|
173
|
-
object = stub(:
|
173
|
+
object = stub(method1: :result1, method2: :result2)
|
174
174
|
assert_equal :result1, object.method1
|
175
175
|
assert_equal :result2, object.method2
|
176
176
|
end
|
data/RELEASE.md
CHANGED
@@ -1,5 +1,33 @@
|
|
1
1
|
# Release Notes
|
2
2
|
|
3
|
+
## 2.3.0
|
4
|
+
|
5
|
+
### External changes
|
6
|
+
|
7
|
+
* Fix nested parameter matching for keyword arguments (f94e2504, #648) - thanks to @CodingAnarchy for reporting
|
8
|
+
|
9
|
+
## 2.2.0
|
10
|
+
|
11
|
+
### External changes
|
12
|
+
|
13
|
+
* Support multiple methods in `responds_with` matcher (f086b7e4, #578) - thanks to @vlad-pisanov for the suggestion
|
14
|
+
* Add block syntax for sequences (93fdffd, #61)
|
15
|
+
* Improve sequence failure message (0800c6ff, #60)
|
16
|
+
* Drop support for Ruby v2.0 (85848fb0, #642)
|
17
|
+
* Include the original test name in expired stub error messages (ca3ff8eb, #641, #642) - thanks to @casperisfine
|
18
|
+
|
19
|
+
* Avoid rubocop directive ending up in YARD docs (2a9ee81a)
|
20
|
+
* Update docs to fix those for `Mock#method_missing` (cee0bad6)
|
21
|
+
* Reinstate missing CNAME for GitHub Pages site (da67bb0d)
|
22
|
+
* Use Ruby v1.9 Hash syntax in docs (6de20726, #625)
|
23
|
+
* Add missing YARD tag for API#sequence name param (343c5979)
|
24
|
+
* Add missing YARD tag for API#states name param (f798df83)
|
25
|
+
|
26
|
+
### Internal changes
|
27
|
+
|
28
|
+
* Tidy up Minitest vs MiniTest references (#626, #614, #615) - thanks to @zenspider & @Maimer for their help
|
29
|
+
* Add Ruby v3.3 to CI build matrix (ce31b544)
|
30
|
+
|
3
31
|
## 2.1.0
|
4
32
|
|
5
33
|
### External changes
|
data/Rakefile
CHANGED
@@ -42,10 +42,10 @@ namespace 'test' do # rubocop:disable Metrics/BlockLength
|
|
42
42
|
end
|
43
43
|
|
44
44
|
namespace 'integration' do
|
45
|
-
desc 'Run
|
45
|
+
desc 'Run Minitest integration tests (intended to be run in its own process)'
|
46
46
|
Rake::TestTask.new('minitest') do |t|
|
47
47
|
t.libs << 'test'
|
48
|
-
t.test_files = FileList['test/integration/
|
48
|
+
t.test_files = FileList['test/integration/minitest_test.rb']
|
49
49
|
t.verbose = true
|
50
50
|
t.warning = true
|
51
51
|
end
|
@@ -93,18 +93,18 @@ end
|
|
93
93
|
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
94
94
|
def benchmark_test_case(klass, iterations)
|
95
95
|
require 'benchmark'
|
96
|
-
require 'mocha/detection/
|
96
|
+
require 'mocha/detection/minitest'
|
97
97
|
|
98
|
-
if defined?(
|
99
|
-
minitest_version = Gem::Version.new(Mocha::Detection::
|
98
|
+
if defined?(Minitest)
|
99
|
+
minitest_version = Gem::Version.new(Mocha::Detection::Minitest.version)
|
100
100
|
if Gem::Requirement.new('>= 5.0.0').satisfied_by?(minitest_version)
|
101
101
|
Minitest.seed = 1
|
102
|
-
result = Benchmark.realtime { iterations.times { |_i| klass.run(
|
103
|
-
|
102
|
+
result = Benchmark.realtime { iterations.times { |_i| klass.run(Minitest::CompositeReporter.new) } }
|
103
|
+
Minitest::Runnable.runnables.delete(klass)
|
104
104
|
result
|
105
105
|
else
|
106
|
-
|
107
|
-
Benchmark.realtime { iterations.times { |_i|
|
106
|
+
Minitest::Unit.output = StringIO.new
|
107
|
+
Benchmark.realtime { iterations.times { |_i| Minitest::Unit.new.run([klass]) } }
|
108
108
|
end
|
109
109
|
else
|
110
110
|
load 'test/unit/ui/console/testrunner.rb' unless defined?(Test::Unit::UI::Console::TestRunner)
|
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.
|
@@ -60,7 +60,7 @@ module Mocha
|
|
60
60
|
#
|
61
61
|
# @example Using expected_methods_vs_return_values Hash to setup expectations.
|
62
62
|
# def test_motor_starts_and_stops
|
63
|
-
# motor = mock('motor', :
|
63
|
+
# motor = mock('motor', start: true, stop: true)
|
64
64
|
# assert motor.start
|
65
65
|
# assert motor.stop
|
66
66
|
# # an error will be raised unless both Motor#start and Motor#stop have been called
|
@@ -88,7 +88,7 @@ module Mocha
|
|
88
88
|
#
|
89
89
|
# @example Using stubbed_methods_vs_return_values Hash to setup stubbed methods.
|
90
90
|
# def test_motor_starts_and_stops
|
91
|
-
# motor = stub('motor', :
|
91
|
+
# motor = stub('motor', start: true, stop: true)
|
92
92
|
# assert motor.start
|
93
93
|
# assert motor.stop
|
94
94
|
# # an error will not be raised even if either Motor#start or Motor#stop has not been called
|
@@ -115,7 +115,7 @@ module Mocha
|
|
115
115
|
#
|
116
116
|
# @example Ignore invocations of irrelevant methods.
|
117
117
|
# def test_motor_stops
|
118
|
-
# motor = stub_everything('motor', :
|
118
|
+
# motor = stub_everything('motor', stop: true)
|
119
119
|
# assert_nil motor.irrelevant_method_1 # => no error raised
|
120
120
|
# assert_nil motor.irrelevant_method_2 # => no error raised
|
121
121
|
# assert motor.stop
|
@@ -131,8 +131,11 @@ module Mocha
|
|
131
131
|
|
132
132
|
# Builds a new sequence which can be used to constrain the order in which expectations can occur.
|
133
133
|
#
|
134
|
-
# 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}.
|
135
136
|
#
|
137
|
+
# @param [String] name name of sequence
|
138
|
+
# @yield optional block within which expectations should be constrained by the sequence
|
136
139
|
# @return [Sequence] a new sequence
|
137
140
|
#
|
138
141
|
# @see Expectation#in_sequence
|
@@ -156,8 +159,23 @@ module Mocha
|
|
156
159
|
#
|
157
160
|
# task_one.execute
|
158
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
|
159
170
|
def sequence(name)
|
160
|
-
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
|
161
179
|
end
|
162
180
|
|
163
181
|
# Builds a new state machine which can be used to constrain the order in which expectations can occur.
|
@@ -170,6 +188,7 @@ module Mocha
|
|
170
188
|
#
|
171
189
|
# A test can contain multiple state machines.
|
172
190
|
#
|
191
|
+
# @param [String] name name of state machine
|
173
192
|
# @return [StateMachine] a new state machine
|
174
193
|
#
|
175
194
|
# @see Expectation#then
|
@@ -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
|
data/lib/mocha/expectation.rb
CHANGED
@@ -632,14 +632,20 @@ module Mocha
|
|
632
632
|
@ordering_constraints.all?(&:allows_invocation_now?)
|
633
633
|
end
|
634
634
|
|
635
|
+
# @private
|
636
|
+
def ordering_constraints_not_allowing_invocation_now
|
637
|
+
@ordering_constraints.reject(&:allows_invocation_now?)
|
638
|
+
end
|
639
|
+
|
635
640
|
# @private
|
636
641
|
def matches_method?(method_name)
|
637
642
|
@method_matcher.match?(method_name)
|
638
643
|
end
|
639
644
|
|
640
645
|
# @private
|
641
|
-
def match?(invocation)
|
642
|
-
@method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && @block_matcher.match?(invocation.block)
|
646
|
+
def match?(invocation, ignoring_order: false)
|
647
|
+
order_independent_match = @method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && @block_matcher.match?(invocation.block)
|
648
|
+
ignoring_order ? order_independent_match : order_independent_match && in_correct_order?
|
643
649
|
end
|
644
650
|
|
645
651
|
# @private
|
@@ -6,9 +6,9 @@ module Mocha
|
|
6
6
|
#
|
7
7
|
# This class should only be used by authors of test libraries and not by typical "users" of Mocha.
|
8
8
|
#
|
9
|
-
# For example, it is used by +Mocha::Integration::
|
9
|
+
# For example, it is used by +Mocha::Integration::Minitest::Adapter+ in order to have Mocha raise a +Minitest::Assertion+ which can then be sensibly handled by +Minitest::Unit::TestCase+.
|
10
10
|
#
|
11
|
-
# @see Mocha::Integration::
|
11
|
+
# @see Mocha::Integration::Minitest::Adapter
|
12
12
|
class ExpectationErrorFactory
|
13
13
|
class << self
|
14
14
|
# @!attribute exception_class
|
@@ -17,7 +17,11 @@ module Mocha
|
|
17
17
|
@expectations.any? { |expectation| expectation.matches_method?(method_name) }
|
18
18
|
end
|
19
19
|
|
20
|
-
def match(invocation)
|
20
|
+
def match(invocation, ignoring_order: false)
|
21
|
+
matching_expectations(invocation, ignoring_order: ignoring_order).first
|
22
|
+
end
|
23
|
+
|
24
|
+
def match_but_out_of_order(invocation)
|
21
25
|
matching_expectations(invocation).first
|
22
26
|
end
|
23
27
|
|
@@ -51,8 +55,8 @@ module Mocha
|
|
51
55
|
|
52
56
|
private
|
53
57
|
|
54
|
-
def matching_expectations(invocation)
|
55
|
-
@expectations.select { |e| e.match?(invocation) }
|
58
|
+
def matching_expectations(invocation, ignoring_order: false)
|
59
|
+
@expectations.select { |e| e.match?(invocation, ignoring_order: ignoring_order) }
|
56
60
|
end
|
57
61
|
end
|
58
62
|
end
|
data/lib/mocha/hooks.rb
CHANGED
@@ -7,12 +7,12 @@ module Mocha
|
|
7
7
|
#
|
8
8
|
# This module is provided as part of the +Mocha::API+ module and is therefore part of the public API, but should only be used by authors of test libraries and not by typical "users" of Mocha.
|
9
9
|
#
|
10
|
-
# Integration with Test::Unit and
|
10
|
+
# Integration with Test::Unit and Minitest are provided as part of Mocha, because they are (or were once) part of the Ruby standard library. Integration with other test libraries is not provided as *part* of Mocha, but is supported by means of the methods in this module.
|
11
11
|
#
|
12
12
|
# See the code in the +Adapter+ modules for examples of how to use the methods in this module. +Mocha::ExpectationErrorFactory+ may be used if you want +Mocha+ to raise a different type of exception.
|
13
13
|
#
|
14
14
|
# @see Mocha::Integration::TestUnit::Adapter
|
15
|
-
# @see Mocha::Integration::
|
15
|
+
# @see Mocha::Integration::Minitest::Adapter
|
16
16
|
# @see Mocha::ExpectationErrorFactory
|
17
17
|
# @see Mocha::API
|
18
18
|
module Hooks
|
@@ -35,8 +35,14 @@ module Mocha
|
|
35
35
|
# Resets Mocha after a test (only for use by authors of test libraries).
|
36
36
|
#
|
37
37
|
# This method should be called after each individual test has finished (including after any "teardown" code).
|
38
|
-
def mocha_teardown
|
39
|
-
Mockery.teardown
|
38
|
+
def mocha_teardown(origin = mocha_test_name)
|
39
|
+
Mockery.teardown(origin)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a string representing the unit test name, to be included in some Mocha
|
43
|
+
# to help track down potential bugs.
|
44
|
+
def mocha_test_name
|
45
|
+
nil
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
@@ -4,21 +4,21 @@ require 'mocha/expectation_error_factory'
|
|
4
4
|
|
5
5
|
module Mocha
|
6
6
|
module Integration
|
7
|
-
module
|
8
|
-
# Integrates Mocha into recent versions of
|
7
|
+
module Minitest
|
8
|
+
# Integrates Mocha into recent versions of Minitest.
|
9
9
|
#
|
10
10
|
# See the source code for an example of how to integrate Mocha into a test library.
|
11
11
|
module Adapter
|
12
12
|
include Mocha::API
|
13
13
|
|
14
14
|
# @private
|
15
|
-
def self.applicable_to?(
|
16
|
-
Gem::Requirement.new('>= 3.3.0').satisfied_by?(
|
15
|
+
def self.applicable_to?(minitest_version)
|
16
|
+
Gem::Requirement.new('>= 3.3.0').satisfied_by?(minitest_version)
|
17
17
|
end
|
18
18
|
|
19
19
|
# @private
|
20
20
|
def self.description
|
21
|
-
'adapter for
|
21
|
+
'adapter for Minitest gem >= v3.3.0'
|
22
22
|
end
|
23
23
|
|
24
24
|
# @private
|
@@ -46,6 +46,21 @@ module Mocha
|
|
46
46
|
super
|
47
47
|
mocha_teardown
|
48
48
|
end
|
49
|
+
|
50
|
+
# @private
|
51
|
+
def mocha_test_name
|
52
|
+
if respond_to?(:name)
|
53
|
+
test_name = name
|
54
|
+
elsif respond_to?(:__name__) # Older minitest
|
55
|
+
test_name = __name__
|
56
|
+
end
|
57
|
+
|
58
|
+
if test_name
|
59
|
+
"#{self.class.name}##{test_name}"
|
60
|
+
else
|
61
|
+
self.class.name
|
62
|
+
end
|
63
|
+
end
|
49
64
|
end
|
50
65
|
end
|
51
66
|
end
|
@@ -2,10 +2,10 @@ require 'mocha/expectation_error'
|
|
2
2
|
|
3
3
|
module Mocha
|
4
4
|
module Integration
|
5
|
-
module
|
5
|
+
module Minitest
|
6
6
|
def self.translate(exception)
|
7
7
|
return exception unless exception.is_a?(::Mocha::ExpectationError)
|
8
|
-
translated_exception = ::
|
8
|
+
translated_exception = ::Minitest::Assertion.new(exception.message)
|
9
9
|
translated_exception.set_backtrace(exception.backtrace)
|
10
10
|
translated_exception
|
11
11
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'mocha/debug'
|
2
|
+
require 'mocha/detection/minitest'
|
3
|
+
require 'mocha/integration/minitest/adapter'
|
4
|
+
|
5
|
+
module Mocha
|
6
|
+
module Integration
|
7
|
+
module Minitest
|
8
|
+
def self.activate
|
9
|
+
target = Detection::Minitest.testcase
|
10
|
+
return false unless target
|
11
|
+
|
12
|
+
minitest_version = Gem::Version.new(Detection::Minitest.version)
|
13
|
+
Debug.puts "Detected Minitest version: #{minitest_version}"
|
14
|
+
|
15
|
+
unless Minitest::Adapter.applicable_to?(minitest_version)
|
16
|
+
raise 'Versions of minitest earlier than v3.3.0 are not supported.'
|
17
|
+
end
|
18
|
+
|
19
|
+
unless target < Minitest::Adapter
|
20
|
+
Debug.puts "Applying #{Minitest::Adapter.description}"
|
21
|
+
target.send(:include, Minitest::Adapter)
|
22
|
+
end
|
23
|
+
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mocha/minitest.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'mocha/ruby_version'
|
2
|
-
require 'mocha/integration/
|
2
|
+
require 'mocha/integration/minitest'
|
3
3
|
|
4
|
-
unless Mocha::Integration::
|
5
|
-
raise "
|
4
|
+
unless Mocha::Integration::Minitest.activate
|
5
|
+
raise "Minitest must be loaded *before* `require 'mocha/minitest'`."
|
6
6
|
end
|
data/lib/mocha/mock.rb
CHANGED
@@ -100,7 +100,7 @@ module Mocha
|
|
100
100
|
#
|
101
101
|
# @example Setup multiple expectations using +expected_methods_vs_return_values+.
|
102
102
|
# object = mock()
|
103
|
-
# object.expects(:
|
103
|
+
# object.expects(expected_method_one: :result_one, expected_method_two: :result_two)
|
104
104
|
#
|
105
105
|
# # is exactly equivalent to
|
106
106
|
#
|
@@ -114,6 +114,7 @@ module Mocha
|
|
114
114
|
method_name = args.shift
|
115
115
|
ensure_method_not_already_defined(method_name)
|
116
116
|
expectation = Expectation.new(self, method_name, backtrace)
|
117
|
+
expectation.in_sequence(@mockery.sequences.last) if @mockery.sequences.any?
|
117
118
|
expectation.returns(args.shift) unless args.empty?
|
118
119
|
@expectations.add(expectation)
|
119
120
|
end
|
@@ -138,7 +139,7 @@ module Mocha
|
|
138
139
|
#
|
139
140
|
# @example Setup multiple expectations using +stubbed_methods_vs_return_values+.
|
140
141
|
# object = mock()
|
141
|
-
# object.stubs(:
|
142
|
+
# object.stubs(stubbed_method_one: :result_one, stubbed_method_two: :result_two)
|
142
143
|
#
|
143
144
|
# # is exactly equivalent to
|
144
145
|
#
|
@@ -153,6 +154,7 @@ module Mocha
|
|
153
154
|
ensure_method_not_already_defined(method_name)
|
154
155
|
expectation = Expectation.new(self, method_name, backtrace)
|
155
156
|
expectation.at_least(0)
|
157
|
+
expectation.in_sequence(@mockery.sequences.last) if @mockery.sequences.any?
|
156
158
|
expectation.returns(args.shift) unless args.empty?
|
157
159
|
@expectations.add(expectation)
|
158
160
|
end
|
@@ -309,12 +311,10 @@ module Mocha
|
|
309
311
|
end
|
310
312
|
|
311
313
|
# @private
|
312
|
-
# rubocop:disable Style/MethodMissingSuper
|
313
|
-
def method_missing(symbol, *arguments, &block)
|
314
|
+
def method_missing(symbol, *arguments, &block) # rubocop:disable Style/MethodMissingSuper
|
314
315
|
handle_method_call(symbol, arguments, block)
|
315
316
|
end
|
316
317
|
ruby2_keywords(:method_missing)
|
317
|
-
# rubocop:enable Style/MethodMissingSuper
|
318
318
|
|
319
319
|
# @private
|
320
320
|
def handle_method_call(symbol, arguments, block)
|
@@ -323,7 +323,7 @@ module Mocha
|
|
323
323
|
invocation = Invocation.new(self, symbol, arguments, block)
|
324
324
|
if (matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(invocation))
|
325
325
|
matching_expectation_allowing_invocation.invoke(invocation)
|
326
|
-
elsif (matching_expectation = all_expectations.match(invocation)) || (!matching_expectation && !@everything_stubbed)
|
326
|
+
elsif (matching_expectation = all_expectations.match(invocation, ignoring_order: true)) || (!matching_expectation && !@everything_stubbed)
|
327
327
|
raise_unexpected_invocation_error(invocation, matching_expectation)
|
328
328
|
end
|
329
329
|
end
|
@@ -343,8 +343,8 @@ module Mocha
|
|
343
343
|
end
|
344
344
|
|
345
345
|
# @private
|
346
|
-
def __expire__
|
347
|
-
@expired = true
|
346
|
+
def __expire__(origin)
|
347
|
+
@expired = origin || true
|
348
348
|
end
|
349
349
|
|
350
350
|
# @private
|
@@ -373,7 +373,11 @@ module Mocha
|
|
373
373
|
if @unexpected_invocation.nil?
|
374
374
|
@unexpected_invocation = invocation
|
375
375
|
matching_expectation.invoke(invocation) if matching_expectation
|
376
|
-
|
376
|
+
call_description = @unexpected_invocation.call_description
|
377
|
+
if matching_expectation && !matching_expectation.in_correct_order?
|
378
|
+
call_description += ' invoked out of order'
|
379
|
+
end
|
380
|
+
message = "#{call_description}\n#{@mockery.mocha_inspect}"
|
377
381
|
else
|
378
382
|
message = @unexpected_invocation.short_call_description
|
379
383
|
end
|
@@ -389,8 +393,10 @@ module Mocha
|
|
389
393
|
def check_expiry
|
390
394
|
return unless @expired
|
391
395
|
|
396
|
+
origin = @expired == true ? 'one test' : @expired
|
397
|
+
|
392
398
|
sentences = [
|
393
|
-
"#{mocha_inspect} was instantiated in
|
399
|
+
"#{mocha_inspect} was instantiated in #{origin} but it is receiving invocations within another test.",
|
394
400
|
'This can lead to unintended interactions between tests and hence unexpected test failures.',
|
395
401
|
'Ensure that every test correctly cleans up any state that it introduces.'
|
396
402
|
]
|
data/lib/mocha/mockery.rb
CHANGED
@@ -48,8 +48,8 @@ module Mocha
|
|
48
48
|
instance.verify(*args)
|
49
49
|
end
|
50
50
|
|
51
|
-
def teardown
|
52
|
-
instance.teardown
|
51
|
+
def teardown(origin = nil)
|
52
|
+
instance.teardown(origin)
|
53
53
|
ensure
|
54
54
|
@instances.pop
|
55
55
|
end
|
@@ -91,9 +91,9 @@ module Mocha
|
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def teardown
|
94
|
+
def teardown(origin = nil)
|
95
95
|
stubba.unstub_all
|
96
|
-
mocks.each(
|
96
|
+
mocks.each { |m| m.__expire__(origin) }
|
97
97
|
reset
|
98
98
|
end
|
99
99
|
|
@@ -109,6 +109,10 @@ module Mocha
|
|
109
109
|
@state_machines ||= []
|
110
110
|
end
|
111
111
|
|
112
|
+
def sequences
|
113
|
+
@sequences ||= []
|
114
|
+
end
|
115
|
+
|
112
116
|
def mocha_inspect
|
113
117
|
message = ''
|
114
118
|
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map(&:mocha_inspect).join("\n- ")}\n" if unsatisfied_expectations.any?
|
data/lib/mocha/object_methods.rb
CHANGED
@@ -59,7 +59,7 @@ module Mocha
|
|
59
59
|
#
|
60
60
|
# @example Setting up multiple expectations on a non-mock object.
|
61
61
|
# product = Product.new
|
62
|
-
# product.expects(
|
62
|
+
# product.expects(valid?: true, save: true)
|
63
63
|
#
|
64
64
|
# # exactly equivalent to
|
65
65
|
#
|
@@ -108,7 +108,7 @@ module Mocha
|
|
108
108
|
#
|
109
109
|
# @example Setting up multiple stubbed methods on a non-mock object.
|
110
110
|
# product = Product.new
|
111
|
-
# product.stubs(
|
111
|
+
# product.stubs(valid?: true, save: true)
|
112
112
|
#
|
113
113
|
# # exactly equivalent to
|
114
114
|
#
|
@@ -21,12 +21,12 @@ module Mocha
|
|
21
21
|
# @example Alternative ways to combine matchers with a logical AND.
|
22
22
|
# object = mock()
|
23
23
|
# object.expects(:run).with(all_of(has_key(:foo), has_key(:bar)))
|
24
|
-
# object.run(:
|
24
|
+
# object.run(foo: 'foovalue', bar: 'barvalue')
|
25
25
|
#
|
26
26
|
# # is exactly equivalent to
|
27
27
|
#
|
28
28
|
# object.expects(:run).with(has_key(:foo) & has_key(:bar))
|
29
|
-
# object.run(:
|
29
|
+
# object.run(foo: 'foovalue', bar: 'barvalue)
|
30
30
|
def &(other)
|
31
31
|
AllOf.new(self, other)
|
32
32
|
end
|
@@ -45,12 +45,12 @@ module Mocha
|
|
45
45
|
# @example Alternative ways to combine matchers with a logical OR.
|
46
46
|
# object = mock()
|
47
47
|
# object.expects(:run).with(any_of(has_key(:foo), has_key(:bar)))
|
48
|
-
# object.run(:
|
48
|
+
# object.run(foo: 'foovalue')
|
49
49
|
#
|
50
50
|
# # is exactly equivalent to
|
51
51
|
#
|
52
52
|
# object.expects(:run).with(has_key(:foo) | has_key(:bar))
|
53
|
-
# object.run(:
|
53
|
+
# object.run(foo: 'foovalue')
|
54
54
|
#
|
55
55
|
# @example Using an explicit {Equals} matcher in combination with {#|}.
|
56
56
|
# object.expects(:run).with(equals(1) | equals(2))
|
@@ -24,7 +24,7 @@ module Mocha
|
|
24
24
|
# @example Actual parameter includes item which matches nested matcher.
|
25
25
|
# object = mock()
|
26
26
|
# object.expects(:method_1).with(includes(has_key(:key)))
|
27
|
-
# object.method_1(['foo', 'bar', {:
|
27
|
+
# object.method_1(['foo', 'bar', {key: 'baz'}])
|
28
28
|
# # no error raised
|
29
29
|
#
|
30
30
|
# @example Actual parameter does not include item matching nested matcher.
|
@@ -44,11 +44,11 @@ module Mocha
|
|
44
44
|
# @example Actual parameter is a Hash including the given key.
|
45
45
|
# object = mock()
|
46
46
|
# object.expects(:method_1).with(includes(:bar))
|
47
|
-
# object.method_1({:
|
47
|
+
# object.method_1({foo: 1, bar: 2})
|
48
48
|
# # no error raised
|
49
49
|
#
|
50
50
|
# @example Actual parameter is a Hash without the given key.
|
51
|
-
# object.method_1({:
|
51
|
+
# object.method_1({foo: 1, baz: 2})
|
52
52
|
# # error raised, because hash does not include key 'bar'
|
53
53
|
#
|
54
54
|
# @example Actual parameter is a Hash with a key matching the given matcher.
|
@@ -13,7 +13,8 @@ module Mocha
|
|
13
13
|
|
14
14
|
def matches?(available_parameters)
|
15
15
|
parameter, is_last_parameter = extract_parameter(available_parameters)
|
16
|
-
|
16
|
+
|
17
|
+
return false unless HasEntries.new(@value).matches?([parameter])
|
17
18
|
|
18
19
|
if is_last_parameter && !same_type_of_hash?(parameter, @value)
|
19
20
|
return false if Mocha.configuration.strict_keyword_argument_matching?
|
@@ -1,12 +1,18 @@
|
|
1
1
|
require 'mocha/parameter_matchers/base'
|
2
|
+
require 'mocha/parameter_matchers/all_of'
|
2
3
|
require 'yaml'
|
3
4
|
|
4
5
|
module Mocha
|
5
6
|
module ParameterMatchers
|
6
|
-
#
|
7
|
+
# @overload def responds_with(message, result)
|
8
|
+
# Matches any object that responds to +message+ with +result+. To put it another way, it tests the quack, not the duck.
|
9
|
+
# @param [Symbol] message method to invoke.
|
10
|
+
# @param [Object] result expected result of sending +message+.
|
11
|
+
# @overload def responds_with(messages_vs_results)
|
12
|
+
# Matches any object that responds to all the messages with the corresponding results as specified by +messages_vs_results+.
|
13
|
+
# @param [Hash<Symbol,Object>] messages_vs_results +Hash+ of messages vs results.
|
14
|
+
# @raise [ArgumentError] if +messages_vs_results+ does not contain at least one entry.
|
7
15
|
#
|
8
|
-
# @param [Symbol] message method to invoke.
|
9
|
-
# @param [Object] result expected result of sending +message+.
|
10
16
|
# @return [RespondsWith] parameter matcher.
|
11
17
|
#
|
12
18
|
# @see Expectation#with
|
@@ -22,8 +28,29 @@ module Mocha
|
|
22
28
|
# object.expects(:method_1).with(responds_with(:upcase, "BAR"))
|
23
29
|
# object.method_1("foo")
|
24
30
|
# # error raised, because "foo".upcase != "BAR"
|
25
|
-
|
26
|
-
|
31
|
+
#
|
32
|
+
# @example Actual parameter responds with "FOO" when :upcase is invoked and "oof" when :reverse is invoked.
|
33
|
+
# object = mock()
|
34
|
+
# object.expects(:method_1).with(responds_with(upcase: "FOO", reverse: "oof"))
|
35
|
+
# object.method_1("foo")
|
36
|
+
# # no error raised, because "foo".upcase == "FOO" and "foo".reverse == "oof"
|
37
|
+
def responds_with(*options)
|
38
|
+
case options.length
|
39
|
+
when 0
|
40
|
+
raise ArgumentError, 'No arguments. Expecting at least one.'
|
41
|
+
when 1
|
42
|
+
option = options.first
|
43
|
+
raise ArgumentError, 'Argument is not a Hash.' unless option.is_a?(Hash)
|
44
|
+
raise ArgumentError, 'Argument has no entries.' if option.empty?
|
45
|
+
|
46
|
+
matchers = option.map { |message, result| RespondsWith.new(message, result) }
|
47
|
+
AllOf.new(*matchers)
|
48
|
+
when 2
|
49
|
+
message, result = options
|
50
|
+
RespondsWith.new(message, result)
|
51
|
+
else
|
52
|
+
raise ArgumentError, 'Too many arguments; use either a single argument (must be a Hash) or two arguments (a message and a result).'
|
53
|
+
end
|
27
54
|
end
|
28
55
|
|
29
56
|
# Parameter matcher which matches if actual parameter returns expected result when specified method is invoked.
|
data/lib/mocha/version.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 = '>= 2.
|
9
|
+
s.required_ruby_version = '>= 2.1'
|
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.'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mocha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Mead
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby2_keywords
|
@@ -58,7 +58,7 @@ files:
|
|
58
58
|
- lib/mocha/configuration.rb
|
59
59
|
- lib/mocha/debug.rb
|
60
60
|
- lib/mocha/deprecation.rb
|
61
|
-
- lib/mocha/detection/
|
61
|
+
- lib/mocha/detection/minitest.rb
|
62
62
|
- lib/mocha/detection/test_unit.rb
|
63
63
|
- lib/mocha/error_with_filtered_backtrace.rb
|
64
64
|
- lib/mocha/exception_raiser.rb
|
@@ -71,9 +71,9 @@ files:
|
|
71
71
|
- lib/mocha/inspect.rb
|
72
72
|
- lib/mocha/instance_method.rb
|
73
73
|
- lib/mocha/integration/assertion_counter.rb
|
74
|
-
- lib/mocha/integration/
|
75
|
-
- lib/mocha/integration/
|
76
|
-
- lib/mocha/integration/
|
74
|
+
- lib/mocha/integration/minitest.rb
|
75
|
+
- lib/mocha/integration/minitest/adapter.rb
|
76
|
+
- lib/mocha/integration/minitest/exception_translation.rb
|
77
77
|
- lib/mocha/integration/monkey_patcher.rb
|
78
78
|
- lib/mocha/integration/test_unit.rb
|
79
79
|
- lib/mocha/integration/test_unit/adapter.rb
|
@@ -141,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
141
|
requirements:
|
142
142
|
- - ">="
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '2.
|
144
|
+
version: '2.1'
|
145
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
147
|
- - ">="
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'mocha/debug'
|
2
|
-
require 'mocha/detection/mini_test'
|
3
|
-
require 'mocha/integration/mini_test/adapter'
|
4
|
-
|
5
|
-
module Mocha
|
6
|
-
module Integration
|
7
|
-
module MiniTest
|
8
|
-
def self.activate
|
9
|
-
target = Detection::MiniTest.testcase
|
10
|
-
return false unless target
|
11
|
-
|
12
|
-
mini_test_version = Gem::Version.new(Detection::MiniTest.version)
|
13
|
-
Debug.puts "Detected MiniTest version: #{mini_test_version}"
|
14
|
-
|
15
|
-
unless MiniTest::Adapter.applicable_to?(mini_test_version)
|
16
|
-
raise 'Versions of minitest earlier than v3.3.0 are not supported.'
|
17
|
-
end
|
18
|
-
|
19
|
-
unless target < MiniTest::Adapter
|
20
|
-
Debug.puts "Applying #{MiniTest::Adapter.description}"
|
21
|
-
target.send(:include, MiniTest::Adapter)
|
22
|
-
end
|
23
|
-
|
24
|
-
true
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|