Skip to content

Commit e34dfb5

Browse files
committed
Spy#mock_all
1 parent 1dc2f18 commit e34dfb5

File tree

5 files changed

+59
-12
lines changed

5 files changed

+59
-12
lines changed

lib/spy.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,23 @@ def off_const(base_module, *constant_names)
110110
def mock(klass, *stubs)
111111
new_mock = Mock.new(klass).new
112112
if stubs.size > 0
113-
Spy.on(new_mock, *stubs)
113+
on(new_mock, *stubs)
114114
end
115115
new_mock
116116
end
117117

118+
def mock_all(klass, *stubs)
119+
mock_klass = Mock.new(klass)
120+
new_mock = mock_klass.new
121+
122+
spies = stubs.size > 0 ? on(new_mock, *stubs) : []
123+
124+
unstubbed_methods = mock_klass.mocked_methods - spies.map(&:method_name)
125+
on(new_mock, *unstubbed_methods) if unstubbed_methods.size > 0
126+
127+
new_mock
128+
end
129+
118130
# unhook all methods
119131
def teardown
120132
Agency.instance.dissolve!

lib/spy/mock.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module Spy
55
# original class it will raise an error.
66
module Mock
77
CLASSES_NOT_TO_OVERRIDE = [Enumerable, Numeric, Comparable, Class, Module, Object]
8+
METHODS_NOT_TO_OVERRIDE = [:initialize, :method]
89

910
def initialize
1011
end
@@ -57,8 +58,10 @@ def new(klass)
5758
def included(mod)
5859
method_classes = classes_to_override_methods(mod)
5960

61+
mocked_methods = []
6062
[:public, :protected, :private].each do |visibility|
6163
get_inherited_methods(method_classes, visibility).each do |method_name|
64+
mocked_methods << method_name
6265
args = args_for_method(mod.instance_method(method_name))
6366

6467
mod.class_eval <<-DEF_METHOD, __FILE__, __LINE__+1
@@ -70,6 +73,10 @@ def #{method_name}(#{args})
7073
DEF_METHOD
7174
end
7275
end
76+
77+
mod.define_singleton_method(:mocked_methods) do
78+
mocked_methods
79+
end
7380
end
7481

7582
private
@@ -86,11 +93,12 @@ def classes_to_override_methods(mod)
8693
end
8794

8895
def get_inherited_methods(klass_ancestors, visibility)
89-
get_methods_method = "#{visibility}_instance_methods".to_sym
90-
instance_methods = klass_ancestors.map(&get_methods_method)
96+
instance_methods = klass_ancestors.map do |klass|
97+
klass.send("#{visibility}_instance_methods".to_sym, false)
98+
end
9199
instance_methods.flatten!
92100
instance_methods.uniq!
93-
instance_methods - Object.send(get_methods_method)
101+
instance_methods - METHODS_NOT_TO_OVERRIDE
94102
end
95103

96104
def args_for_method(method)

test/integration/test_mocking.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'test_helper'
2+
3+
class TestMocking < MiniTest::Unit::TestCase
4+
def teardown
5+
Spy::Agency.instance.dissolve!
6+
end
7+
8+
def test_spy_on_mock_does_not_raise
9+
mock = Spy.mock(Pen)
10+
spy = Spy.on(mock, :write).and_return(:awesome)
11+
assert_equal :awesome, mock.write("hello")
12+
assert spy.has_been_called?
13+
end
14+
15+
def test_spy_mock_shortcuts
16+
mock = Spy.mock(Pen, :another, write_hello: :goodbye)
17+
assert_nil mock.another
18+
assert_equal :goodbye, mock.write_hello
19+
end
20+
21+
def test_spy_mock_all
22+
mock = Spy.mock_all(Pen)
23+
assert_nil mock.another
24+
end
25+
end

test/integration/test_subroutine_spying.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,4 @@ def test_spy_on_double_does_not_raise
4747
assert_equal :dumb, double.doubles_are
4848
assert spy.has_been_called?
4949
end
50-
51-
def test_spy_on_mock_does_not_raise
52-
mock = Spy.mock(Pen)
53-
spy = Spy.on(mock, :write).and_return(:awesome)
54-
assert_equal :awesome, mock.write("hello")
55-
assert spy.has_been_called?
56-
end
5750
end

test/spy/test_mock.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ def write_hello(other)
88
end
99

1010
def setup
11-
@pen = Spy.mock(BluePen)
11+
@pen_mock = Mock.new(BluePen)
12+
@pen = @pen_mock.new
1213
end
1314

1415
def teardown
@@ -67,6 +68,14 @@ def test_that_and_call_original_works
6768
end
6869
end
6970

71+
def test_mocked_methods
72+
pen_methods = Pen.public_instance_methods(false) +
73+
Pen.protected_instance_methods(false) +
74+
Pen.private_instance_methods(false)
75+
pen_methods.delete(:initialize)
76+
assert_equal pen_methods.sort, @pen_mock.mocked_methods.sort
77+
end
78+
7079
def test_base_class_methods_are_not_stubbed
7180
(Object.instance_methods - [:tap, :pretty_print_inspect]).each do |method_name|
7281
object_method = Object.instance_method(method_name)

0 commit comments

Comments
 (0)