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
|
require File.expand_path('../../test_helper', __FILE__)
require 'mocha/ruby_version'
require 'method_definer'
require 'mocha/class_methods'
require 'mocha/mockery'
require 'mocha/mock'
require 'mocha/instance_method'
class InstanceMethodTest < Mocha::TestCase
include MethodDefiner
include Mocha
def class_with_method(method, result = nil)
Class.new do
extend ClassMethods
singleton_class.extend(ClassMethods)
singleton_class.send(:define_method, method) { result } if method
end
end
def test_should_not_raise_error_hiding_method_that_isnt_defined
klass = class_with_method(:irrelevant)
method = InstanceMethod.new(klass, :method_x)
assert_nothing_raised { method.hide_original_method }
end
def test_should_not_raise_error_hiding_method_in_class_that_implements_method_called_method
klass = class_with_method(:method)
method = InstanceMethod.new(klass, :method)
assert_nothing_raised { method.hide_original_method }
end
def test_should_define_a_new_method_which_should_call_mocha_method_missing
klass = class_with_method(:method_x)
mocha = build_mock
define_instance_method(klass, :mocha) { mocha }
mocha.expects(:method_x).with(:param1, :param2).returns(:result)
method = InstanceMethod.new(klass, :method_x)
method.hide_original_method
method.define_new_method
result = klass.method_x(:param1, :param2)
assert_equal :result, result
assert mocha.__verified__?
end
def test_should_include_the_filename_and_line_number_in_exceptions
klass = class_with_method(:method_x)
mocha = build_mock
define_instance_method(klass, :mocha) { mocha }
mocha.stubs(:method_x).raises(Exception)
method = InstanceMethod.new(klass, :method_x)
method.hide_original_method
method.define_new_method
expected_filename = 'stubbed_method.rb'
expected_line_number = 47
exception = assert_raises(Exception) { klass.method_x }
matching_line = exception.backtrace.find do |line|
filename, line_number, _context = line.split(':')
filename.include?(expected_filename) && line_number.to_i == expected_line_number
end
assert_not_nil matching_line, "Expected to find #{expected_filename}:#{expected_line_number} in the backtrace:\n #{exception.backtrace.join("\n")}"
end
def test_should_remove_new_method
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
method.remove_new_method
assert_equal false, klass.respond_to?(:method_x)
end
def test_remove_new_method_restores_original_method
klass = class_with_method(:method_x, :original_result)
klass.singleton_class.send(:alias_method, :_method, :method)
method = InstanceMethod.new(klass, :method_x)
method.hide_original_method
method.define_new_method
method.remove_new_method
assert klass.respond_to?(:method_x)
assert_equal :original_result, klass.method_x
end
def test_remove_new_method_restores_original_method_accepting_a_block_parameter
klass = Class.new do
extend ClassMethods
singleton_class.extend(ClassMethods)
def self.method_x(&block)
block.call if block_given?
end
end
klass.singleton_class.send(:alias_method, :_method, :method)
method = InstanceMethod.new(klass, :method_x)
method.hide_original_method
method.define_new_method
method.remove_new_method
block_called = false
klass.method_x { block_called = true }
assert block_called
end
def test_should_call_hide_original_method
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
method.hide_original_method
define_instance_accessor(method, :hide_called)
replace_instance_method(method, :hide_original_method) { self.hide_called = true }
method.stub
assert method.hide_called
end
def test_should_call_define_new_method
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
define_instance_accessor(method, :define_called)
replace_instance_method(method, :define_new_method) { self.define_called = true }
method.stub
assert method.define_called
end
def test_should_call_remove_new_method
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
mocha = build_mock
define_instance_method(klass, :mocha) { mocha }
replace_instance_method(method, :reset_mocha) {}
define_instance_accessor(method, :remove_called)
replace_instance_method(method, :remove_new_method) { self.remove_called = true }
method.unstub
assert method.remove_called
end
def test_should_call_mocha_unstub
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
mocha = Class.new do
class << self
attr_accessor :unstub_method
end
def self.unstub(method)
self.unstub_method = method
end
end
define_instance_method(mocha, :any_expectations?) { true }
replace_instance_method(method, :mock) { mocha }
method.unstub
assert_equal mocha.unstub_method, :method_x
end
def test_should_call_stubbee_reset_mocha_if_no_expectations_remaining
klass = class_with_method(:method_x)
method = InstanceMethod.new(klass, :method_x)
replace_instance_method(method, :remove_new_method) {}
mocha = Class.new
define_instance_method(mocha, :unstub) { |method_name| }
define_instance_method(mocha, :any_expectations?) { false }
replace_instance_method(method, :mock) { mocha }
stubbee = Class.new do
attr_accessor :reset_mocha_called
def reset_mocha
self.reset_mocha_called = true
end
end.new
replace_instance_method(method, :stubbee) { stubbee }
method.unstub
assert stubbee.reset_mocha_called
end
def test_should_return_mock_for_stubbee
mocha = Object.new
stubbee = Object.new
define_instance_method(stubbee, :mocha) { mocha }
method = InstanceMethod.new(stubbee, :method_name)
assert_equal mocha, method.mock
end
def test_should_not_match_if_other_object_has_a_different_class
method = InstanceMethod.new(Object.new, :method)
other_object = Object.new
assert !method.matches?(other_object)
end
def test_should_not_match_if_other_instance_method_has_different_stubbee
stubbee1 = Object.new
stubbee2 = Object.new
method1 = InstanceMethod.new(stubbee1, :method)
method2 = InstanceMethod.new(stubbee2, :method)
assert !method1.matches?(method2)
end
def test_should_not_match_if_other_instance_method_has_different_method
stubbee = Object.new
method1 = InstanceMethod.new(stubbee, :method_1)
method2 = InstanceMethod.new(stubbee, :method_2)
assert !method1.matches?(method2)
end
def test_should_match_if_other_instance_method_has_same_stubbee_and_same_method_so_no_attempt_is_made_to_stub_a_method_twice
stubbee = Object.new
method1 = InstanceMethod.new(stubbee, :method)
method2 = InstanceMethod.new(stubbee, :method)
assert method1.matches?(method2)
end
def test_should_match_if_other_instance_method_has_same_stubbee_and_same_method_but_stubbee_equal_method_lies_like_active_record_association_proxy
stubbee = Class.new do
extend ClassMethods
def equal?(_other)
false
end
end.new
method1 = InstanceMethod.new(stubbee, :method)
method2 = InstanceMethod.new(stubbee, :method)
assert method1.matches?(method2)
end
private
def build_mock
Mock.new(Mockery.new)
end
end
|