muack 1.5.1 → 1.7.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/.gitlab-ci.yml +40 -0
- data/.gitmodules +1 -1
- data/CHANGES.md +26 -0
- data/README.md +2 -2
- data/lib/muack/block.rb +14 -4
- data/lib/muack/definition.rb +1 -1
- data/lib/muack/mock.rb +54 -22
- data/lib/muack/session.rb +4 -0
- data/lib/muack/version.rb +1 -1
- data/muack.gemspec +5 -7
- data/task/README.md +1 -1
- data/task/gemgem.rb +3 -1
- data/test/test_any_instance_of.rb +11 -0
- data/test/test_keyargs.rb +3 -0
- data/test/test_mock.rb +148 -7
- data/test/test_prepend.rb +29 -0
- data/test/test_visibility.rb +47 -9
- metadata +4 -6
- data/.travis.yml +0 -21
- data/lib/muack/block_26.rb +0 -16
- data/lib/muack/block_27.rb +0 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87b3de29deb805feea133c6e8fc7b3fc2720334df701a59452acc3141fd63509
|
|
4
|
+
data.tar.gz: aeb2e74419effc23ca0d1b51de935308242fd0fa12e9dae6be064dc11cc7e8ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d67d586cb7005f3ec8fae297cf6e9bc7f669cc1853dc5c293b28858fb3b7f6134c7e373399f5135fb88ab3879122e8f6c61a653925a456bab3a53715549a3de
|
|
7
|
+
data.tar.gz: a6387f685b6db8c25e447027698de5f47cc8aea2abef864552bc2d3010e5c5f92e637df9dd08ab6bdb3692e40c598ad6c01b1c7fae4d4e59672e9f66eae6fcf9
|
data/.gitlab-ci.yml
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
stages:
|
|
3
|
+
- test
|
|
4
|
+
|
|
5
|
+
.test:
|
|
6
|
+
stage: test
|
|
7
|
+
image: ruby:${RUBY_VERSION}-bullseye
|
|
8
|
+
variables:
|
|
9
|
+
GIT_DEPTH: "1"
|
|
10
|
+
GIT_SUBMODULE_STRATEGY: recursive
|
|
11
|
+
GIT_SUBMODULE_PATHS: task
|
|
12
|
+
RUBYOPT: --enable-frozen-string-literal
|
|
13
|
+
before_script:
|
|
14
|
+
- bundle install --retry=3
|
|
15
|
+
- unset CI # Coverage doesn't work well with frozen literal
|
|
16
|
+
script:
|
|
17
|
+
- ruby -vr bundler/setup -S rake test
|
|
18
|
+
|
|
19
|
+
ruby:3.0:
|
|
20
|
+
extends:
|
|
21
|
+
- .test
|
|
22
|
+
variables:
|
|
23
|
+
RUBY_VERSION: '3.0'
|
|
24
|
+
|
|
25
|
+
ruby:3.1:
|
|
26
|
+
extends:
|
|
27
|
+
- .test
|
|
28
|
+
variables:
|
|
29
|
+
RUBY_VERSION: '3.1'
|
|
30
|
+
|
|
31
|
+
ruby:3.2:
|
|
32
|
+
extends:
|
|
33
|
+
- .test
|
|
34
|
+
variables:
|
|
35
|
+
RUBY_VERSION: '3.2'
|
|
36
|
+
|
|
37
|
+
jruby:latest:
|
|
38
|
+
extends:
|
|
39
|
+
- .test
|
|
40
|
+
image: jruby:latest
|
data/.gitmodules
CHANGED
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# CHANGES
|
|
2
2
|
|
|
3
|
+
## Muack 1.7.0 -- 2022-12-29
|
|
4
|
+
|
|
5
|
+
### Incompatible changes
|
|
6
|
+
|
|
7
|
+
* Drop support for Ruby 2.6-
|
|
8
|
+
|
|
9
|
+
### Bugs fixed
|
|
10
|
+
|
|
11
|
+
* Fixed stubbed instance method not following the original visibility.
|
|
12
|
+
It's always public before this fix.
|
|
13
|
+
* Worked around a few JRuby 9.4 compatibility issues. Note that there are
|
|
14
|
+
still some issues due to JRuby bugs. Those tests are currently skipped.
|
|
15
|
+
|
|
16
|
+
## Muack 1.6.0 -- 2020-12-06
|
|
17
|
+
|
|
18
|
+
### Enhancement
|
|
19
|
+
|
|
20
|
+
* Fix a few cases for mocking against modules/classes with prepended modules,
|
|
21
|
+
especially when `any_instance_of` is also used in combination. Previously,
|
|
22
|
+
it's either not mocking correctly or it may affect modules/classes which
|
|
23
|
+
also use the same prepended modules. For mocking prepended methods, an
|
|
24
|
+
internal `MuackPrepended` module will be prepended into the modules/classes
|
|
25
|
+
to properly override the prepended methods. This module cannot be removed
|
|
26
|
+
between tests because there's no way to do that with current Rubies.
|
|
27
|
+
* Performance could be potentially slightly improved with Ruby 2.6+
|
|
28
|
+
|
|
3
29
|
## Muack 1.5.1 -- 2020-12-06
|
|
4
30
|
|
|
5
31
|
### Bugs fixed
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Muack [](https://gitlab.com/godfat/muack/-/pipelines)
|
|
2
2
|
|
|
3
3
|
by Lin Jen-Shin ([godfat](http://godfat.org))
|
|
4
4
|
|
|
@@ -1221,7 +1221,7 @@ Or, I am happy to break legacy.
|
|
|
1221
1221
|
|
|
1222
1222
|
Apache License 2.0 (Apache-2.0)
|
|
1223
1223
|
|
|
1224
|
-
Copyright (c) 2013-
|
|
1224
|
+
Copyright (c) 2013-2022, Lin Jen-Shin (godfat)
|
|
1225
1225
|
|
|
1226
1226
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
1227
1227
|
you may not use this file except in compliance with the License.
|
data/lib/muack/block.rb
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
module Muack
|
|
3
|
+
class Block < Struct.new(:block, :context)
|
|
4
|
+
def initialize block, context=nil
|
|
5
|
+
super
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def call(...)
|
|
9
|
+
if context
|
|
10
|
+
context.instance_exec(...)
|
|
11
|
+
else
|
|
12
|
+
block.call(...)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
6
16
|
end
|
data/lib/muack/definition.rb
CHANGED
data/lib/muack/mock.rb
CHANGED
|
@@ -112,22 +112,18 @@ module Muack
|
|
|
112
112
|
private
|
|
113
113
|
def __mock_inject_method defi
|
|
114
114
|
__mock_injected[defi.msg] = defi
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# otherwise the last prepended module.
|
|
118
|
-
# b) would be the class in AnyInstanceOf.
|
|
119
|
-
target = object.singleton_class.ancestors.first
|
|
115
|
+
target = Mock.prepare_target(object.singleton_class, defi.msg)
|
|
116
|
+
defi.target = target
|
|
120
117
|
Mock.store_original_method(target, defi)
|
|
121
118
|
__mock_inject_mock_method(target, defi)
|
|
122
119
|
end
|
|
123
120
|
|
|
124
121
|
def __mock_reset_method defi
|
|
125
|
-
|
|
122
|
+
defi.target.module_eval do
|
|
126
123
|
remove_method(defi.msg)
|
|
127
124
|
# restore original method
|
|
128
|
-
if
|
|
129
|
-
|
|
130
|
-
private_instance_methods(false).include?(defi.original_method)
|
|
125
|
+
if defi.original_method &&
|
|
126
|
+
Mock.direct_method_defined?(self, defi.original_method)
|
|
131
127
|
alias_method(defi.msg, defi.original_method)
|
|
132
128
|
__send__(defi.visibility, defi.msg)
|
|
133
129
|
remove_method(defi.original_method)
|
|
@@ -135,33 +131,69 @@ module Muack
|
|
|
135
131
|
end
|
|
136
132
|
end
|
|
137
133
|
|
|
138
|
-
def self.
|
|
139
|
-
|
|
134
|
+
def self.direct_method_defined? mod, msg
|
|
135
|
+
mod.method_defined?(msg, false) || # this doesn't cover private method
|
|
136
|
+
mod.private_method_defined?(msg, false)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def self.method_visibility mod, msg, inherit=false
|
|
140
|
+
if mod.public_method_defined?(msg, inherit)
|
|
140
141
|
:public
|
|
141
|
-
elsif
|
|
142
|
+
elsif mod.protected_method_defined?(msg, inherit)
|
|
142
143
|
:protected
|
|
143
|
-
elsif
|
|
144
|
+
elsif mod.private_method_defined?(msg, inherit)
|
|
144
145
|
:private
|
|
145
146
|
end
|
|
147
|
+
end
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
def self.prepare_target singleton_class, msg
|
|
150
|
+
if singleton_class == singleton_class.ancestors.first # no prepended mod
|
|
151
|
+
singleton_class
|
|
152
|
+
else # check if we need to prepend an internal module to override
|
|
153
|
+
index = singleton_class.ancestors.index(singleton_class)
|
|
154
|
+
prepended_modules = singleton_class.ancestors[0...index]
|
|
155
|
+
|
|
156
|
+
if prepended_modules.find{ |m| direct_method_defined?(m, msg) }
|
|
157
|
+
# prepend an internal module to override the prepended module(s)
|
|
158
|
+
name = :MuackPrepended
|
|
159
|
+
if singleton_class.const_defined?(name)
|
|
160
|
+
singleton_class.const_get(name)
|
|
161
|
+
else
|
|
162
|
+
prepended = ::Module.new
|
|
163
|
+
singleton_class.const_set(name, prepended)
|
|
164
|
+
singleton_class.private_constant(name)
|
|
165
|
+
singleton_class.prepend(prepended)
|
|
166
|
+
prepended
|
|
167
|
+
end
|
|
168
|
+
else # we don't need to override so singleton class is enough
|
|
169
|
+
singleton_class
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.store_original_method mod, defi
|
|
175
|
+
if visibility = method_visibility(mod, defi.msg)
|
|
176
|
+
# Defined in itself, we need to make alias
|
|
177
|
+
original_method = find_new_name(mod, defi.msg)
|
|
178
|
+
mod.__send__(:alias_method, original_method, defi.msg)
|
|
150
179
|
defi.original_method = original_method
|
|
151
180
|
defi.visibility = visibility
|
|
152
|
-
|
|
181
|
+
elsif visibility = method_visibility(mod, defi.msg, true)
|
|
182
|
+
# Defined in parent, we can just override
|
|
183
|
+
defi.visibility = visibility
|
|
184
|
+
else # Not defined, pick a reasonable default
|
|
153
185
|
defi.visibility = :public
|
|
154
186
|
end
|
|
155
187
|
end
|
|
156
188
|
|
|
157
|
-
def self.find_new_name
|
|
189
|
+
def self.find_new_name mod, message, level=0
|
|
158
190
|
if level >= (::ENV['MUACK_RECURSION_LEVEL'] || 9).to_i
|
|
159
191
|
raise CannotFindInjectionName.new(level+1, message)
|
|
160
192
|
end
|
|
161
193
|
|
|
162
194
|
new_name = "__muack_#{name}_#{level}_#{message}".to_sym
|
|
163
|
-
if
|
|
164
|
-
find_new_name(
|
|
195
|
+
if direct_method_defined?(mod, new_name)
|
|
196
|
+
find_new_name(mod, message, level+1)
|
|
165
197
|
else
|
|
166
198
|
new_name
|
|
167
199
|
end
|
|
@@ -246,12 +278,12 @@ module Muack
|
|
|
246
278
|
::Kernel.instance_method(:method).bind(object).call(method_name).
|
|
247
279
|
super_method
|
|
248
280
|
|
|
249
|
-
if super_method.owner
|
|
281
|
+
if super_method.owner.kind_of?(::Class) && super_method.name == :new
|
|
250
282
|
initialize_method = ::Class.instance_method(:instance_method).
|
|
251
283
|
bind(object).call(:initialize)
|
|
252
284
|
__mock_block_with_kargs?(initialize_method)
|
|
253
285
|
else
|
|
254
|
-
|
|
286
|
+
__mock_block_with_kargs?(super_method)
|
|
255
287
|
end
|
|
256
288
|
end
|
|
257
289
|
|
data/lib/muack/session.rb
CHANGED
|
@@ -22,6 +22,10 @@ module Muack
|
|
|
22
22
|
def verify obj=nil
|
|
23
23
|
if obj
|
|
24
24
|
with(obj, :[]).all?(&:__mock_verify)
|
|
25
|
+
elsif RUBY_ENGINE == 'jruby'
|
|
26
|
+
# Workaround weird error:
|
|
27
|
+
# TypeError: Muack::Stub#to_ary should return Array
|
|
28
|
+
data.each_value.all?{ |v| v.__mock_verify }
|
|
25
29
|
else
|
|
26
30
|
data.each_value.all?(&:__mock_verify)
|
|
27
31
|
end
|
data/lib/muack/version.rb
CHANGED
data/muack.gemspec
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: muack 1.
|
|
2
|
+
# stub: muack 1.7.0 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "muack".freeze
|
|
6
|
-
s.version = "1.
|
|
6
|
+
s.version = "1.7.0"
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
|
10
10
|
s.authors = ["Lin Jen-Shin (godfat)".freeze]
|
|
11
|
-
s.date = "
|
|
11
|
+
s.date = "2022-12-29"
|
|
12
12
|
s.description = "Muack -- A fast, small, yet powerful mocking library.\n\nInspired by [RR][], and it's 32x times faster (750s vs 23s) than RR\nfor running [Rib][] tests.\n\n[RR]: https://github.com/rr/rr\n[Rib]: https://github.com/godfat/rib".freeze
|
|
13
13
|
s.email = ["godfat (XD) godfat.org".freeze]
|
|
14
14
|
s.files = [
|
|
15
15
|
".gitignore".freeze,
|
|
16
|
+
".gitlab-ci.yml".freeze,
|
|
16
17
|
".gitmodules".freeze,
|
|
17
|
-
".travis.yml".freeze,
|
|
18
18
|
"CHANGES.md".freeze,
|
|
19
19
|
"Gemfile".freeze,
|
|
20
20
|
"LICENSE".freeze,
|
|
@@ -23,8 +23,6 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
"lib/muack.rb".freeze,
|
|
24
24
|
"lib/muack/any_instance_of.rb".freeze,
|
|
25
25
|
"lib/muack/block.rb".freeze,
|
|
26
|
-
"lib/muack/block_26.rb".freeze,
|
|
27
|
-
"lib/muack/block_27.rb".freeze,
|
|
28
26
|
"lib/muack/coat.rb".freeze,
|
|
29
27
|
"lib/muack/definition.rb".freeze,
|
|
30
28
|
"lib/muack/error.rb".freeze,
|
|
@@ -54,7 +52,7 @@ Gem::Specification.new do |s|
|
|
|
54
52
|
"test/test_visibility.rb".freeze]
|
|
55
53
|
s.homepage = "https://github.com/godfat/muack".freeze
|
|
56
54
|
s.licenses = ["Apache-2.0".freeze]
|
|
57
|
-
s.rubygems_version = "3.1
|
|
55
|
+
s.rubygems_version = "3.4.1".freeze
|
|
58
56
|
s.summary = "Muack -- A fast, small, yet powerful mocking library.".freeze
|
|
59
57
|
s.test_files = [
|
|
60
58
|
"test/test_any_instance_of.rb".freeze,
|
data/task/README.md
CHANGED
|
@@ -39,7 +39,7 @@ end
|
|
|
39
39
|
|
|
40
40
|
Apache License 2.0 (Apache-2.0)
|
|
41
41
|
|
|
42
|
-
Copyright (c) 2011-
|
|
42
|
+
Copyright (c) 2011-2021, Lin Jen-Shin (godfat)
|
|
43
43
|
|
|
44
44
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
45
45
|
you may not use this file except in compliance with the License.
|
data/task/gemgem.rb
CHANGED
|
@@ -42,6 +42,7 @@ module Gemgem
|
|
|
42
42
|
|
|
43
43
|
def gem_install
|
|
44
44
|
require 'rubygems/commands/install_command'
|
|
45
|
+
require 'rubygems/package'
|
|
45
46
|
# read ~/.gemrc
|
|
46
47
|
Gem.use_paths(Gem.configuration[:gemhome], Gem.configuration[:gempath])
|
|
47
48
|
Gem::Command.extra_args = Gem.configuration[:gem]
|
|
@@ -51,7 +52,8 @@ module Gemgem
|
|
|
51
52
|
cmd.handle_options([])
|
|
52
53
|
|
|
53
54
|
# install
|
|
54
|
-
|
|
55
|
+
gem_package = Gem::Package.new(gem_path)
|
|
56
|
+
install = Gem::Installer.new(gem_package, cmd.options)
|
|
55
57
|
install.install
|
|
56
58
|
puts "\e[35mGem installed: \e[33m#{strip_path(install.gem_dir)}\e[0m"
|
|
57
59
|
end
|
|
@@ -113,6 +113,17 @@ describe Muack::AnyInstanceOf do
|
|
|
113
113
|
obj.f.should.eq 0
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
describe 'mock any_instance_of on a method defined higher up' do
|
|
117
|
+
methods_count = klass.instance_methods.size
|
|
118
|
+
|
|
119
|
+
would 'not store a backup method' do
|
|
120
|
+
any_instance_of(klass){ |inst| mock(inst).to_s{ 'to_s' } }
|
|
121
|
+
|
|
122
|
+
expect(klass.new.to_s).eq 'to_s'
|
|
123
|
+
expect(klass.instance_methods.size).eq methods_count
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
116
127
|
# Brought from rspec-mocks and it's currently failing on rspec-mocks
|
|
117
128
|
would 'stub any_instance_of on module extending it self' do
|
|
118
129
|
mod = Module.new {
|
data/test/test_keyargs.rb
CHANGED
|
@@ -50,6 +50,9 @@ describe Muack::Mock do
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
would 'instance method' do
|
|
53
|
+
# https://github.com/jruby/jruby/issues/7545
|
|
54
|
+
skip if RUBY_ENGINE == 'jruby' && obj.kind_of?(Muack::AnyInstanceOf)
|
|
55
|
+
|
|
53
56
|
mock(obj).bonjour(a: 0, b: 1)
|
|
54
57
|
|
|
55
58
|
expect(instance.bonjour(a: 0, b: 1)).eq([0, 1])
|
data/test/test_mock.rb
CHANGED
|
@@ -104,10 +104,73 @@ describe Muack::Mock do
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
describe 'not affect the original module' do
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
def mod
|
|
108
|
+
@mod ||= Module.new{ def f; :f; end }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def setup type
|
|
112
|
+
m = mod
|
|
113
|
+
Array.new(2).map{ Class.new{ public_send(type, m) }.new }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
would 'with include and mock' do
|
|
117
|
+
c0, c1 = setup(:include)
|
|
118
|
+
|
|
119
|
+
mock(c0).f{:g}
|
|
120
|
+
|
|
121
|
+
expect(c0.f).eq :g
|
|
122
|
+
expect(c1.f).eq :f
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
would 'with prepend and mock' do
|
|
126
|
+
c0, c1 = setup(:prepend)
|
|
127
|
+
|
|
128
|
+
mock(c0).f{:g}
|
|
129
|
+
|
|
130
|
+
expect(c0.f).eq :g
|
|
131
|
+
expect(c1.f).eq :f
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
would 'with include and mock any_instance_of C0' do
|
|
135
|
+
c0, c1 = setup(:include)
|
|
136
|
+
|
|
137
|
+
mock(any_instance_of(c0.class)).f{:g}
|
|
138
|
+
|
|
139
|
+
expect(c0.f).eq :g
|
|
140
|
+
expect(c1.f).eq :f
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
would 'with prepend and mock any_instance_of C0' do
|
|
144
|
+
c0, c1 = setup(:prepend)
|
|
145
|
+
|
|
146
|
+
mock(any_instance_of(c0.class)).f{:g}
|
|
147
|
+
|
|
148
|
+
expect(c0.f).eq :g
|
|
149
|
+
expect(c1.f).eq :f
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
would 'with include and mock any_instance_of M' do
|
|
153
|
+
c0, c1 = setup(:include)
|
|
154
|
+
|
|
155
|
+
mock(any_instance_of(mod)).f{:g}.times(2)
|
|
156
|
+
|
|
157
|
+
expect(c0.f).eq :g
|
|
158
|
+
expect(c1.f).eq :g
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
would 'with prepend and mock any_instance_of M' do
|
|
162
|
+
c0, c1 = setup(:prepend)
|
|
163
|
+
|
|
164
|
+
mock(any_instance_of(mod)).f{:g}.times(2)
|
|
165
|
+
|
|
166
|
+
expect(c0.f).eq :g
|
|
167
|
+
expect(c1.f).eq :g
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
would 'with extend on the instance' do
|
|
171
|
+
m = mod
|
|
172
|
+
c0 = Class.new.new.extend(m)
|
|
173
|
+
c1 = Class.new{ prepend m }.new
|
|
111
174
|
|
|
112
175
|
mock(c0).f{:g}
|
|
113
176
|
|
|
@@ -115,9 +178,10 @@ describe Muack::Mock do
|
|
|
115
178
|
expect(c1.f).eq :f
|
|
116
179
|
end
|
|
117
180
|
|
|
118
|
-
would 'with prepend' do
|
|
119
|
-
m =
|
|
120
|
-
c0 = Class.new
|
|
181
|
+
would 'with prepend on the singleton class of instance' do
|
|
182
|
+
m = mod
|
|
183
|
+
c0 = Class.new.new
|
|
184
|
+
c0.singleton_class.prepend m
|
|
121
185
|
c1 = Class.new{ prepend m }.new
|
|
122
186
|
|
|
123
187
|
mock(c0).f{:g}
|
|
@@ -125,6 +189,83 @@ describe Muack::Mock do
|
|
|
125
189
|
expect(c0.f).eq :g
|
|
126
190
|
expect(c1.f).eq :f
|
|
127
191
|
end
|
|
192
|
+
|
|
193
|
+
describe 'with prepend on any_instance_of' do
|
|
194
|
+
describe 'on prepended method' do
|
|
195
|
+
would 'have a muack prepended module' do
|
|
196
|
+
m = mod
|
|
197
|
+
c = Class.new{ prepend m }
|
|
198
|
+
ancestors_size = c.ancestors.size
|
|
199
|
+
|
|
200
|
+
mock(any_instance_of(c)).f{:g}
|
|
201
|
+
|
|
202
|
+
expect(c.new.f).eq :g
|
|
203
|
+
expect(c).const_defined?(:MuackPrepended)
|
|
204
|
+
expect(c.ancestors.size).eq ancestors_size + 1
|
|
205
|
+
|
|
206
|
+
expect(Muack.verify).eq true
|
|
207
|
+
|
|
208
|
+
# Make sure there's only one MuackPrepended
|
|
209
|
+
mock(any_instance_of(c)).f{:h}
|
|
210
|
+
expect(c.ancestors.size).eq ancestors_size + 1
|
|
211
|
+
expect(c.new.f).eq :h
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
describe 'on non-prepended method' do
|
|
216
|
+
would 'not have a muack prepended module' do
|
|
217
|
+
m = mod
|
|
218
|
+
c = Class.new{ def g; :g; end; prepend m }
|
|
219
|
+
ancestors_size = c.ancestors.size
|
|
220
|
+
|
|
221
|
+
mock(any_instance_of(c)).g{:m}
|
|
222
|
+
|
|
223
|
+
expect(c.new.f).eq :f
|
|
224
|
+
expect(c.new.g).eq :m
|
|
225
|
+
expect(c).not.const_defined?(:MuackPrepended)
|
|
226
|
+
expect(c.ancestors.size).eq ancestors_size
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
describe 'any_instance_of on a module which has a prepended module' do
|
|
232
|
+
before do
|
|
233
|
+
@m0 = m0 = Module.new{ def f; :m0; end }
|
|
234
|
+
@m1 = m1 = Module.new{ def f; :m1; end; prepend m0 }
|
|
235
|
+
@c0 = Class.new{ prepend m0 }.new
|
|
236
|
+
@c1 = Class.new{ prepend m1 }.new
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
would 'any_instance_of m0' do
|
|
240
|
+
mock(any_instance_of(@m0)).f{:g}.times(2)
|
|
241
|
+
|
|
242
|
+
expect(@c0.f).eq :g
|
|
243
|
+
expect(@c1.f).eq :g
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
would 'any_instance_of m1' do
|
|
247
|
+
skip if RUBY_ENGINE == 'jruby'
|
|
248
|
+
|
|
249
|
+
mock(any_instance_of(@m1)).f{:g}
|
|
250
|
+
|
|
251
|
+
expect(@c0.f).eq :m0
|
|
252
|
+
expect(@c1.f).eq :g
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
would 'any_instance_of c0.class' do
|
|
256
|
+
mock(any_instance_of(@c0.class)).f{:g}
|
|
257
|
+
|
|
258
|
+
expect(@c0.f).eq :g
|
|
259
|
+
expect(@c1.f).eq :m0
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
would 'any_instance_of c1.class' do
|
|
263
|
+
mock(any_instance_of(@c1.class)).f{:g}
|
|
264
|
+
|
|
265
|
+
expect(@c0.f).eq :m0
|
|
266
|
+
expect(@c1.f).eq :g
|
|
267
|
+
end
|
|
268
|
+
end
|
|
128
269
|
end
|
|
129
270
|
end
|
|
130
271
|
|
data/test/test_prepend.rb
CHANGED
|
@@ -94,6 +94,35 @@ describe 'mock with prepend' do
|
|
|
94
94
|
paste :test
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
+
describe 'class with a chain of prepended modules' do
|
|
98
|
+
would 'not affect other modules' do
|
|
99
|
+
mod0 = Module.new{ def f; :m0; end }
|
|
100
|
+
mod1 = Module.new{ def f; :m1; end }
|
|
101
|
+
klass0 = Class.new{ prepend mod0 }
|
|
102
|
+
klass1 = Class.new{ prepend mod1 }
|
|
103
|
+
klass = Class.new{ prepend mod1; prepend mod0 }
|
|
104
|
+
|
|
105
|
+
mock(any_instance_of(klass)).f{:f}
|
|
106
|
+
|
|
107
|
+
expect(klass.new.f).eq :f
|
|
108
|
+
expect(klass0.new.f).eq :m0
|
|
109
|
+
expect(klass1.new.f).eq :m1
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe 'class and subclass' do
|
|
114
|
+
would 'work for prepended superclass' do
|
|
115
|
+
mod = Module.new{ def f; :f; end }
|
|
116
|
+
base = Class.new{ prepend mod }
|
|
117
|
+
sub = Class.new(base)
|
|
118
|
+
|
|
119
|
+
mock(any_instance_of(base)).f{:g}.times(2)
|
|
120
|
+
|
|
121
|
+
expect(base.new.f).eq :g
|
|
122
|
+
expect(sub.new.f).eq :g
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
97
126
|
# Brought from rspec-mocks and it's currently failing on rspec-mocks
|
|
98
127
|
# See https://github.com/rspec/rspec-mocks/pull/1218
|
|
99
128
|
would "handle stubbing prepending methods that were only defined on the prepended module" do
|
data/test/test_visibility.rb
CHANGED
|
@@ -18,17 +18,9 @@ describe 'retain visibility' do
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def generate visibility
|
|
21
|
-
klass = Class.new
|
|
22
|
-
def greet
|
|
23
|
-
'hi'
|
|
24
|
-
end
|
|
25
|
-
end
|
|
21
|
+
klass = Class.new
|
|
26
22
|
|
|
27
23
|
mod = Module.new do
|
|
28
|
-
def greet
|
|
29
|
-
hello
|
|
30
|
-
end
|
|
31
|
-
|
|
32
24
|
def hello
|
|
33
25
|
'hello'
|
|
34
26
|
end
|
|
@@ -97,8 +89,54 @@ describe 'retain visibility' do
|
|
|
97
89
|
paste :test
|
|
98
90
|
end
|
|
99
91
|
|
|
92
|
+
describe 'set the same visibility from the original method' do
|
|
93
|
+
copy :test do
|
|
94
|
+
def find_visibilities
|
|
95
|
+
%i[public protected private].map do |v|
|
|
96
|
+
object.send("#{v}_methods").include?(:hello)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
would do
|
|
101
|
+
current_visibilities = find_visibilities
|
|
102
|
+
|
|
103
|
+
stub(object).hello{ :stub }
|
|
104
|
+
|
|
105
|
+
expect(find_visibilities).eq current_visibilities
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe 'for instance method' do
|
|
110
|
+
def object
|
|
111
|
+
@object ||= Class.new do
|
|
112
|
+
private
|
|
113
|
+
def hello; :hello; end
|
|
114
|
+
end.new
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
paste :test
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe 'for singleton method' do
|
|
121
|
+
def object
|
|
122
|
+
@object ||= begin
|
|
123
|
+
ret = Object.new
|
|
124
|
+
def ret.hello; :hello; end
|
|
125
|
+
ret
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
paste :test
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
100
133
|
# Brought from rspec-mocks
|
|
101
134
|
would "correctly restore the visibility of methods whose visibility has been tweaked on the singleton class" do
|
|
135
|
+
# JRuby didn't store the visibility change on the singleton class,
|
|
136
|
+
# therefore it cannot be properly detected and visibility change
|
|
137
|
+
# will be lost upon reset.
|
|
138
|
+
skip if RUBY_ENGINE == 'jruby'
|
|
139
|
+
|
|
102
140
|
# hello is a private method when mixed in, but public on the module
|
|
103
141
|
# itself
|
|
104
142
|
mod = Module.new do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: muack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lin Jen-Shin (godfat)
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-12-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |-
|
|
14
14
|
Muack -- A fast, small, yet powerful mocking library.
|
|
@@ -25,8 +25,8 @@ extensions: []
|
|
|
25
25
|
extra_rdoc_files: []
|
|
26
26
|
files:
|
|
27
27
|
- ".gitignore"
|
|
28
|
+
- ".gitlab-ci.yml"
|
|
28
29
|
- ".gitmodules"
|
|
29
|
-
- ".travis.yml"
|
|
30
30
|
- CHANGES.md
|
|
31
31
|
- Gemfile
|
|
32
32
|
- LICENSE
|
|
@@ -35,8 +35,6 @@ files:
|
|
|
35
35
|
- lib/muack.rb
|
|
36
36
|
- lib/muack/any_instance_of.rb
|
|
37
37
|
- lib/muack/block.rb
|
|
38
|
-
- lib/muack/block_26.rb
|
|
39
|
-
- lib/muack/block_27.rb
|
|
40
38
|
- lib/muack/coat.rb
|
|
41
39
|
- lib/muack/definition.rb
|
|
42
40
|
- lib/muack/error.rb
|
|
@@ -83,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
83
81
|
- !ruby/object:Gem::Version
|
|
84
82
|
version: '0'
|
|
85
83
|
requirements: []
|
|
86
|
-
rubygems_version: 3.1
|
|
84
|
+
rubygems_version: 3.4.1
|
|
87
85
|
signing_key:
|
|
88
86
|
specification_version: 4
|
|
89
87
|
summary: Muack -- A fast, small, yet powerful mocking library.
|
data/.travis.yml
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
sudo: false
|
|
2
|
-
language: ruby
|
|
3
|
-
|
|
4
|
-
install: 'gem update --system; gem install bundler; bundle install --retry=3'
|
|
5
|
-
before_script: unset CI
|
|
6
|
-
script: 'ruby -vwr bundler/setup -S rake test'
|
|
7
|
-
|
|
8
|
-
matrix:
|
|
9
|
-
include:
|
|
10
|
-
- rvm: 2.4
|
|
11
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
|
12
|
-
- rvm: 2.5
|
|
13
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
|
14
|
-
- rvm: 2.6
|
|
15
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
|
16
|
-
- rvm: 2.7
|
|
17
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
|
18
|
-
- rvm: ruby-head
|
|
19
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
|
20
|
-
- rvm: jruby
|
|
21
|
-
env: RUBYOPT=--enable-frozen-string-literal
|
data/lib/muack/block_26.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module Muack
|
|
3
|
-
class Block < Struct.new(:block, :context)
|
|
4
|
-
def initialize block, context=nil
|
|
5
|
-
super
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def call(*args, &block)
|
|
9
|
-
if context
|
|
10
|
-
context.instance_exec(*args, &block)
|
|
11
|
-
else
|
|
12
|
-
block.call(*args, &block)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
data/lib/muack/block_27.rb
DELETED