mocha 2.1.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|