Class: Muack::Mock
- Inherits:
- BasicObject
- Defined in:
- lib/muack/mock.rb
Instance Attribute Summary collapse
-
#object ⇒ Object
readonly
Returns the value of attribute object.
Instance Method Summary collapse
-
#__mock_class ⇒ Object
used for Muack::Modifier#times to determine if it’s a mock or not.
-
#__mock_defis_pop(defi) ⇒ Object
used for Muack::Modifier#times.
-
#__mock_defis_push(defi) ⇒ Object
used for Muack::Modifier#times.
-
#__mock_dispatch(msg, actual_args) ⇒ Object
used for mocked object to dispatch mocked method.
-
#__mock_dispatch_call(context, disp, actual_args, actual_block, &_yield) ⇒ Object
used for mocked object to dispatch mocked method.
-
#__mock_reset ⇒ Object
used for Muack::Session#reset.
-
#__mock_verify ⇒ Object
used for Muack::Session#verify.
-
#initialize(object) ⇒ Mock
constructor
A new instance of Mock.
-
#inspect ⇒ Object
Public API: Bacon needs this, or we often ended up with stack overflow.
-
#method_missing(msg, *args, &block) ⇒ Object
Public API: Define mocked method.
Constructor Details
#initialize(object) ⇒ Mock
Returns a new instance of Mock.
13 14 15 16 17 18 19 |
# File 'lib/muack/mock.rb', line 13 def initialize object @object = object @__mock_injected = {} [:__mock_defis=, :__mock_disps=].each do |m| __send__(m, ::Hash.new{ |h, k| h[k] = [] }) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(msg, *args, &block) ⇒ Object
Public API: Define mocked method
27 28 29 30 31 32 33 34 35 36 |
# File 'lib/muack/mock.rb', line 27 def method_missing msg, *args, &block defi = Definition.new(msg, args, block) if injected = __mock_injected[defi.msg] defi.original_method = injected.original_method else __mock_inject_method(defi) end __mock_defis_push(defi) Modifier.new(self, defi) end |
Instance Attribute Details
#object ⇒ Object (readonly)
Returns the value of attribute object.
12 13 14 |
# File 'lib/muack/mock.rb', line 12 def object @object end |
Instance Method Details
#__mock_class ⇒ Object
used for Muack::Modifier#times to determine if it’s a mock or not
49 50 51 |
# File 'lib/muack/mock.rb', line 49 def __mock_class (class << self; self; end).superclass end |
#__mock_defis_pop(defi) ⇒ Object
used for Muack::Modifier#times
44 45 46 |
# File 'lib/muack/mock.rb', line 44 def __mock_defis_pop defi __mock_defis[defi.msg].pop end |
#__mock_defis_push(defi) ⇒ Object
used for Muack::Modifier#times
39 40 41 |
# File 'lib/muack/mock.rb', line 39 def __mock_defis_push defi __mock_defis[defi.msg] << defi end |
#__mock_dispatch(msg, actual_args) ⇒ Object
used for mocked object to dispatch mocked method
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/muack/mock.rb', line 54 def __mock_dispatch msg, actual_args if defi = __mock_defis[msg].shift __mock_disps_push(defi) if __mock_check_args(defi.args, actual_args) defi else Mock.__send__(:raise, # Wrong argument Unexpected.new(object, [defi], msg, actual_args)) end else defis = __mock_disps[msg] if expected = defis.find{ |d| __mock_check_args(d.args, actual_args) } Mock.__send__(:raise, # Too many times Expected.new(object, expected, defis.size, defis.size+1)) else Mock.__send__(:raise, # Wrong argument Unexpected.new(object, defis, msg, actual_args)) end end end |
#__mock_dispatch_call(context, disp, actual_args, actual_block, &_yield) ⇒ Object
used for mocked object to dispatch mocked method
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 |
# File 'lib/muack/mock.rb', line 76 def __mock_dispatch_call context, disp, actual_args, actual_block, &_yield args = if disp.peek_args __mock_block_call(context, disp.peek_args, actual_args, actual_block, true) else actual_args end ret = if disp.returns __mock_block_call(context, disp.returns, args, actual_block, true) elsif disp.original_method # proxies for singleton methods context.__send__(disp.original_method, *args, &actual_block) else # proxies for instance methods # need the original context for calling `super` # ruby: can't pass a block to yield, so we name it _yield _yield.call(args, &actual_block) end if disp.peek_return __mock_block_call(context, disp.peek_return, ret, EmptyBlock, false) else ret end end |
#__mock_reset ⇒ Object
used for Muack::Session#reset
114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/muack/mock.rb', line 114 def __mock_reset __mock_injected.each_value do |defi| object.singleton_class.module_eval do remove_method(defi.msg) # restore original method if instance_methods(false).include?(defi.original_method) || private_instance_methods(false).include?(defi.original_method) alias_method(defi.msg, defi.original_method) remove_method(defi.original_method) end end end end |
#__mock_verify ⇒ Object
used for Muack::Session#verify
103 104 105 106 107 108 109 110 111 |
# File 'lib/muack/mock.rb', line 103 def __mock_verify __mock_defis.values.all?(&:empty?) || begin msg, defis_with_same_msg = __mock_defis.find{ |_, v| v.size > 0 } args, defis = defis_with_same_msg.group_by(&:args).first dsize = __mock_disps[msg].select{ |d| d.args == args }.size Mock.__send__(:raise, # Too little times Expected.new(object, defis.first, defis.size + dsize, dsize)) end end |
#inspect ⇒ Object
Public API: Bacon needs this, or we often ended up with stack overflow
22 23 24 |
# File 'lib/muack/mock.rb', line 22 def inspect "Muack::API.#{__mock_class.name[/\w+$/].downcase}(#{object.inspect})" end |