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.



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

#objectObject (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_classObject

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
# 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
    __mock_failed(msg, actual_args)
  end
end

#__mock_dispatch_call(context, disp, actual_args, actual_block, &_yield) ⇒ Object

used for mocked object to dispatch mocked method



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

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_resetObject

used for Muack::Session#reset



107
108
109
# File 'lib/muack/mock.rb', line 107

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

#__mock_verifyObject

used for Muack::Session#verify



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

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

#inspectObject

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