Class: Muack::Mock

Inherits:
BasicObject
Defined in:
lib/muack/mock.rb

Direct Known Subclasses

Coat, Spy, Stub

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object) ⇒ Mock

Returns a new instance of Mock.



11
12
13
14
15
16
17
# File 'lib/muack/mock.rb', line 11

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, &returns) ⇒ Object

Public API: Define mocked method



25
26
27
28
29
30
31
32
33
34
# File 'lib/muack/mock.rb', line 25

def method_missing msg, *args, &returns
  defi = Definition.new(msg, args, returns)
  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

#objectObject (readonly)

Returns the value of attribute object.



10
11
12
# File 'lib/muack/mock.rb', line 10

def object
  @object
end

Instance Method Details

#__mock_classObject

used for Muack::Modifier#times to determine if it’s a mock or not



47
48
49
# File 'lib/muack/mock.rb', line 47

def __mock_class
  (class << self; self; end).superclass
end

#__mock_defis_pop(defi) ⇒ Object

used for Muack::Modifier#times



42
43
44
# File 'lib/muack/mock.rb', line 42

def __mock_defis_pop defi
  __mock_defis[defi.msg].pop
end

#__mock_defis_push(defi) ⇒ Object

used for Muack::Modifier#times



37
38
39
# File 'lib/muack/mock.rb', line 37

def __mock_defis_push defi
  __mock_defis[defi.msg] << defi
end

#__mock_dispatch(actual_call) ⇒ Object

used for mocked object to dispatch mocked method



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/muack/mock.rb', line 52

def __mock_dispatch actual_call
  if defi = __mock_defis[actual_call.msg].shift
    __mock_disps_push(defi)
    if __mock_check_args(defi, actual_call)
      defi
    else
      Mock.__send__(:raise, # Wrong argument
        Unexpected.new(object, [defi], actual_call))
    end
  else
    __mock_failed(actual_call)
  end
end

#__mock_dispatch_call(context, disp, actual_call, &proxy_super) ⇒ Object

used for mocked object to dispatch mocked method



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
# File 'lib/muack/mock.rb', line 67

def __mock_dispatch_call context, disp, actual_call, &proxy_super
  # resolving arguments
  call =
    if disp.peek_args
      args = __mock_block_call(context, disp.peek_args, actual_call)
      ActualCall.new(actual_call.msg, args, actual_call.block)
    else
      actual_call
    end

  # retrieve actual return
  ret =
    if disp.returns
      __mock_block_call(context, disp.returns, call)
    else
      __mock_proxy_call(context, disp, call, proxy_super)
    end

  # resolving return
  if disp.peek_return
    __mock_block_call(context, disp.peek_return, ret, true)
  else
    ret
  end
end

#__mock_resetObject

used for Muack::Session#reset



105
106
107
# File 'lib/muack/mock.rb', line 105

def __mock_reset
  __mock_injected.each_value{ |defi| __mock_reset_method(defi) }
end

#__mock_verifyObject

used for Muack::Session#verify



94
95
96
97
98
99
100
101
102
# File 'lib/muack/mock.rb', line 94

def __mock_verify
  __mock_defis.values.all?(&:empty?) || begin
    msg, defis_with_same_msg = __mock_defis.find{ |_, v| v.any? }
    args, defis = defis_with_same_msg.group_by(&:args).first
    dsize = __mock_disps[msg].count{ |d| d.args == args }
    Mock.__send__(:raise,   # Too little times
      Expected.new(object, defis.first, defis.size + dsize, dsize))
  end
end

#inspectObject

Public API: Bacon needs this, or we often ended up with stack overflow



20
21
22
# File 'lib/muack/mock.rb', line 20

def inspect
  "Muack::API.#{__mock_class.name[/\w+$/].downcase}(#{object.inspect})"
end