1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
require 'test_helper'
module Spy
class TestSubroutine < Minitest::Test
def spy_on(base_object, method_name)
Subroutine.new(base_object, method_name).hook
end
def setup
@pen = Pen.new
end
def teardown
Spy::Agency.instance.dissolve!
end
def test_spy_on_hook_and_saves_spy
pen_write_spy = spy_on(@pen, :write).and_return("hello")
assert_equal "hello", @pen.write(nil)
assert_kind_of Subroutine, pen_write_spy
assert_equal [pen_write_spy], Agency.instance.spies
assert pen_write_spy.has_been_called?
end
def test_spy_can_hook_and_record_a_method_call
pen_write_spy = spy_on(@pen, :write)
refute pen_write_spy.has_been_called?
@pen.write("hello")
assert pen_write_spy.has_been_called?
assert_empty @pen.written
end
def test_spy_can_hook_and_record_a_method_call_on_a_constant
another_spy = spy_on(Pen, :another)
refute another_spy.has_been_called?
assert_nil Pen.another
assert another_spy.has_been_called?
another_spy.unhook
assert_equal "another", Pen.another
end
def test_spy_can_hook_and_record_a_meta_method_call_on_a_constant
assert_equal "meta_class_method", Pen.meta_class_method
meta_spy = spy_on(Pen, :meta_class_method)
refute meta_spy.has_been_called?
assert_nil Pen.meta_class_method
assert meta_spy.has_been_called?
meta_spy.unhook
assert_equal "meta_class_method", Pen.meta_class_method
end
def test_spy_can_hook_record_and_unhook_a_meta_method
assert_equal "meta_method", @pen.meta_method
meta_spy = spy_on(@pen, :meta_method)
refute meta_spy.has_been_called?
assert_nil @pen.meta_method
assert meta_spy.has_been_called?
meta_spy.unhook
assert_equal "meta_method", @pen.meta_method
end
def test_spy_can_unhook_a_method
pen_write_spy = spy_on(@pen, :write)
pen_write_spy.unhook
assert_equal "hello", @pen.write("hello")
refute pen_write_spy.has_been_called?
end
def test_spy_cannot_hook_a_non_existent_method
spy = Subroutine.new(@pen, :no_method)
assert_raises NameError do
spy.hook
end
end
def test_spy_can_hook_a_non_existent_method_if_param_set
Subroutine.new(@pen, :no_method).hook(force:true).and_return(:yep)
assert_equal :yep, @pen.no_method
end
def test_spy_and_return_returns_the_set_value
result = "hello world"
spy_on(@pen, :write).and_return(result)
assert_equal result, @pen.write(nil)
end
def test_spy_and_raise_raises_the_set_exception
pen_write_spy = spy_on(@pen, :write).and_raise(ArgumentError, "problems!")
assert_kind_of Subroutine, pen_write_spy
assert_equal [pen_write_spy], Agency.instance.spies
e = assert_raises ArgumentError do
@pen.write(nil)
end
assert_equal "problems!", e.message
assert pen_write_spy.has_been_called?
end
def test_spy_and_return_can_call_a_block
result = "hello world"
spy_on(@pen, :write).and_return {}.and_return do |string|
string.reverse
end
assert_equal result.reverse, @pen.write(result)
assert_empty @pen.written
end
def test_spy_and_return_can_call_a_block_raises_when_there_is_an_arity_mismatch
write_spy = spy_on(@pen, :write)
write_spy.and_return do |*args|
end
write_spy.and_return do |string, *args|
end
assert_raises ArgumentError do
write_spy.and_return do |string, b|
end
end
write_spy.and_return(force: true) do |string, b|
end
end
def test_spy_and_return_can_call_a_block_that_recieves_a_block
string = "hello world"
spy_on(@pen, :write_block).and_return do |&block|
block.call
end
result = @pen.write_block do
string
end
assert_equal string, result
end
def test_spy_hook_records_number_of_calls
pen_write_spy = spy_on(@pen, :write)
assert_equal 0, pen_write_spy.calls.size
5.times do |i|
@pen.write("hello world")
assert_equal i + 1, pen_write_spy.calls.size
end
end
def test_has_been_called_with?
pen_write_spy = spy_on(@pen, :write)
refute pen_write_spy.has_been_called_with?("hello")
@pen.write("hello")
assert pen_write_spy.has_been_called_with?("hello")
@pen.write("world")
assert pen_write_spy.has_been_called_with?("hello")
@pen.write("hello world")
assert pen_write_spy.has_been_called_with?("hello")
end
def test_spy_hook_records_number_of_calls2
args = ["hello world"]
block = Proc.new {}
pen_write_spy = spy_on(@pen, :write)
called_from = "#{__FILE__}:#{__LINE__ + 1}:in `#{__method__}'"
@pen.write(*args, &block)
call_log = pen_write_spy.calls.first
assert_equal @pen, call_log.object
assert_equal args, call_log.args
assert_equal block, call_log.block
assert_equal called_from, call_log.called_from
end
def test_that_method_spy_keeps_arity
spy_on(@pen, :write)
@pen.write("hello world")
assert_raises ArgumentError do
@pen.write("hello", "world")
end
spy_on(@pen, :write_hello)
@pen.write_hello
assert_raises ArgumentError do
@pen.write_hello("hello")
end
spy_on(@pen, :write_array)
@pen.write_hello
assert_raises ArgumentError do
@pen.write_hello("hello")
end
spy_on(@pen, :greet)
@pen.greet("bob")
assert_raises ArgumentError do
@pen.greet
end
assert_raises ArgumentError do
@pen.greet("hello", "bob", "error")
end
end
def test_that_method_spy_keeps_arity_with_optional_keyword_args
spy_on(@pen, :opt_kwargs)
@pen.opt_kwargs(:pos1)
@pen.opt_kwargs(:pos1, opt: 1, opt2: 2)
assert_raises ArgumentError do
@pen.opt_kwargs
end
assert_raises ArgumentError do
@pen.opt_kwargs(:pos1, :pos2, opt: 1)
end
end
def test_that_method_spy_keeps_arity_with_keyword_splat
spy_on(@pen, :keyrest)
@pen.keyrest
@pen.keyrest(a: 1, b: 2)
assert_raises ArgumentError do
@pen.keyrest(:pos1, :pos2)
end
end
def test_that_method_spy_keeps_arity_with_required_keyword_args
spy_on(@pen, :req_kwargs)
@pen.req_kwargs(req1: 1, req2: 2)
assert_raises ArgumentError do
@pen.req_kwargs
end
assert_raises ArgumentError do
@pen.req_kwargs(:pos1, :pos2)
end
end
def test_hook_mimics_public_visibility
spy_on(@pen, :public_method)
assert @pen.singleton_class.public_method_defined? :public_method
end
def test_hook_mimics_protected_visibility
spy_on(@pen, :protected_method)
assert @pen.singleton_class.protected_method_defined? :protected_method
end
def test_hook_mimics_private_visibility
spy_on(@pen, :private_method)
assert @pen.singleton_class.private_method_defined? :private_method
end
def test_hook_mimics_class_public_visibility
spy_on(Pen, :public_method)
assert Pen.public_method_defined? :public_method
Spy.off(Pen, :public_method)
assert Pen.public_method_defined? :public_method
end
def test_hook_mimics_class_protected_visibility
spy_on(Pen, :protected_method)
assert Pen.protected_method_defined? :protected_method
Spy.off(Pen, :protected_method)
assert Pen.protected_method_defined? :protected_method
end
def test_hook_mimics_class_private_visibility
spy_on(Pen, :private_method)
assert Pen.private_method_defined? :private_method
Spy.off(Pen, :private_method)
assert Pen.private_method_defined? :private_method
end
def test_spy_get_can_retrieve_a_spy
pen_write_spy = spy_on(@pen, :write).and_return(:hello)
assert_equal :hello, @pen.write(:world)
assert Subroutine.get(@pen, :write).has_been_called?
assert_same pen_write_spy, Subroutine.get(@pen, :write)
end
def test_spy_hook_raises_an_error_on_an_already_hooked_method
spy_on(@pen, :write)
assert_raises AlreadyHookedError do
spy_on(@pen, :write)
end
end
end
end
|