Class | RR::Injections::DoubleInjection |
In: |
lib/rr/injections/double_injection.rb
|
Parent: | Injection |
RR::DoubleInjection is the binding of an subject and a method. A double_injection has 0 to many Double objects. Each Double has Argument Expectations and Times called Expectations.
MethodArguments | = | Struct.new(:arguments, :block) |
BoundObjects | = | {} |
doubles | [R] | |
method_name | [R] | |
subject_class | [R] |
# File lib/rr/injections/double_injection.rb, line 95 95: def initialize(subject_class, method_name) 96: @subject_class = subject_class 97: @method_name = method_name.to_sym 98: @doubles = [] 99: @dispatch_method_delegates_to_dispatch_original_method = nil 100: end
RR::DoubleInjection#bind injects a method that acts as a dispatcher that dispatches to the matching Double when the method is called.
# File lib/rr/injections/double_injection.rb, line 111 111: def bind 112: if subject_has_method_defined?(method_name) 113: bind_method_with_alias 114: else 115: Injections::MethodMissingInjection.find_or_create(subject_class) 116: Injections::SingletonMethodAddedInjection.find_or_create(subject_class) 117: bind_method_that_self_destructs_and_delegates_to_method_missing 118: end 119: self 120: end
# File lib/rr/injections/double_injection.rb, line 140 140: def bind_method 141: id = BoundObjects.size 142: BoundObjects[id] = subject_class 143: 144: subject_class.class_eval("def \#{method_name}(*args, &block)\narguments = MethodArguments.new(args, block)\nobj = ::RR::Injections::DoubleInjection::BoundObjects[\#{id}]\nRR::Injections::DoubleInjection.dispatch_method(self, obj, :\#{method_name}, arguments.arguments, arguments.block)\nend\n", __FILE__, __LINE__ + 1) 145: self 146: end
# File lib/rr/injections/double_injection.rb, line 124 124: def bind_method_that_self_destructs_and_delegates_to_method_missing 125: id = BoundObjects.size 126: BoundObjects[id] = subject_class 127: 128: subject_class.class_eval("def \#{method_name}(*args, &block)\n::RR::Injections::DoubleInjection::BoundObjects[\#{id}].class_eval do\nremove_method(:\#{method_name})\nend\nmethod_missing(:\#{method_name}, *args, &block)\nend\n", __FILE__, __LINE__ + 1) 129: self 130: end
# File lib/rr/injections/double_injection.rb, line 34 34: def dispatch_method(subject, subject_class, method_name, arguments, block) 35: subject_eigenclass = (class << subject; self; end) 36: if ( 37: exists?(subject_class, method_name) && 38: (subject_class == subject_eigenclass) || !subject.is_a?(Class) 39: ) 40: find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, block) 41: else 42: new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, block) 43: end 44: end
# File lib/rr/injections/double_injection.rb, line 179 179: def dispatch_method(subject, args, block) 180: if @dispatch_method_delegates_to_dispatch_original_method 181: dispatch_original_method(subject, args, block) 182: else 183: dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block) 184: dispatch.call 185: end 186: end
# File lib/rr/injections/double_injection.rb, line 201 201: def dispatch_method_delegates_to_dispatch_original_method 202: @dispatch_method_delegates_to_dispatch_original_method = true 203: yield 204: ensure 205: @dispatch_method_delegates_to_dispatch_original_method = nil 206: end
# File lib/rr/injections/double_injection.rb, line 188 188: def dispatch_original_method(subject, args, block) 189: dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block) 190: dispatch.call_original_method 191: end
# File lib/rr/injections/double_injection.rb, line 26 26: def exists?(subject_class, method_name) 27: !!find(subject_class, method_name) 28: end
# File lib/rr/injections/double_injection.rb, line 30 30: def exists_by_subject?(subject, method_name) 31: exists?((class << subject; self; end), method_name) 32: end
# File lib/rr/injections/double_injection.rb, line 18 18: def find(subject_class, method_name) 19: instances[subject_class] && instances[subject_class][method_name.to_sym] 20: end
# File lib/rr/injections/double_injection.rb, line 22 22: def find_by_subject(subject, method_name) 23: find(class << subject; self; end, method_name) 24: end
# File lib/rr/injections/double_injection.rb, line 8 8: def find_or_create(subject_class, method_name) 9: instances[subject_class][method_name.to_sym] ||= begin 10: new(subject_class, method_name.to_sym).bind 11: end 12: end
# File lib/rr/injections/double_injection.rb, line 14 14: def find_or_create_by_subject(subject, method_name) 15: find_or_create(class << subject; self; end, method_name) 16: end
# File lib/rr/injections/double_injection.rb, line 83 83: def instances 84: @instances ||= HashWithObjectIdKey.new do |hash, subject_class| 85: hash.set_with_object_id(subject_class, {}) 86: end 87: end
# File lib/rr/injections/double_injection.rb, line 197 197: def original_method_alias_name 198: "__rr__original_#{@method_name}" 199: end
RR::DoubleInjection#register_double adds the passed in Double into this DoubleInjection‘s list of Double objects.
# File lib/rr/injections/double_injection.rb, line 104 104: def register_double(double) 105: @doubles << double 106: end
# File lib/rr/injections/double_injection.rb, line 46 46: def reset 47: instances.each do |subject_class, method_double_map| 48: SingletonMethodAddedInjection.find(subject_class) && SingletonMethodAddedInjection.find(subject_class).reset 49: method_double_map.keys.each do |method_name| 50: reset_double(subject_class, method_name) 51: end 52: Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances.has_key?(subject_class) 53: end 54: end
It binds the original method implementation on the subject if one exists.
# File lib/rr/injections/double_injection.rb, line 167 167: def reset 168: if subject_has_original_method? 169: subject_class.__send__(:remove_method, method_name) 170: subject_class.__send__(:alias_method, method_name, original_method_alias_name) 171: subject_class.__send__(:remove_method, original_method_alias_name) 172: else 173: if subject_has_method_defined?(method_name) 174: subject_class.__send__(:remove_method, method_name) 175: end 176: end 177: end
Resets the DoubleInjection for the passed in subject and method_name.
# File lib/rr/injections/double_injection.rb, line 77 77: def reset_double(subject_class, method_name) 78: double_injection = Injections::DoubleInjection.instances[subject_class].delete(method_name) 79: double_injection.reset 80: Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances[subject_class].empty? 81: end
# File lib/rr/injections/double_injection.rb, line 193 193: def subject_has_original_method_missing? 194: class_instance_method_defined(subject_class, MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name) 195: end
# File lib/rr/injections/double_injection.rb, line 56 56: def verify(*subjects) 57: subject_classes = subjects.empty? ? 58: Injections::DoubleInjection.instances.keys : 59: subjects.map {|subject| class << subject; self; end} 60: subject_classes.each do |subject_class| 61: instances.include?(subject_class) && 62: instances[subject_class].keys.each do |method_name| 63: verify_double(subject_class, method_name) 64: end && 65: instances.delete(subject_class) 66: end 67: end
RR::DoubleInjection#verify verifies each Double TimesCalledExpectation are met.
# File lib/rr/injections/double_injection.rb, line 157 157: def verify 158: @doubles.each do |double| 159: double.verify 160: end 161: end
Verifies the DoubleInjection for the passed in subject and method_name.
# File lib/rr/injections/double_injection.rb, line 70 70: def verify_double(subject_class, method_name) 71: Injections::DoubleInjection.find(subject_class, method_name).verify 72: ensure 73: reset_double subject_class, method_name 74: end
# File lib/rr/injections/double_injection.rb, line 216 216: def bind_method_with_alias 217: subject_class.__send__(:alias_method, original_method_alias_name, method_name) 218: bind_method 219: end