Module: Spy

Defined in:
lib/spy.rb,
lib/spy/api.rb,
lib/spy/base.rb,
lib/spy/mock.rb,
lib/spy/nest.rb,
lib/spy/agency.rb,
lib/spy/version.rb,
lib/spy/call_log.rb,
lib/spy/constant.rb,
lib/spy/exceptions.rb,
lib/spy/subroutine.rb,
lib/spy/integration.rb

Defined Under Namespace

Modules: API, Base, MiniTestAdapter, Mock, TestUnitAdapter Classes: Agency, CallLog, Constant, Nest, RspecAdapter, Subroutine

Constant Summary collapse

VERSION =
"1.0.5"
Error =
Class.new(StandardError)
AlreadyStubbedError =
Class.new(Error)
AlreadyHookedError =
Class.new(Error)
NotHookedError =
Class.new(Error)
NeverHookedError =
Class.new(Error)
NoSpyError =
Class.new(Error)

Class Method Summary collapse

Class Method Details

.get(base_object, *method_names) ⇒ Subroutine+

retrieve the spy from an object

Parameters:

  • base_object
  • method_names

    *[Symbol]

Returns:



156
157
158
159
160
161
162
# File 'lib/spy.rb', line 156

def get(base_object, *method_names)
  spies = method_names.map do |method_name|
    Subroutine.get(base_object, method_name)
  end

  spies.size > 1 ? spies : spies.first
end

.get_const(base_module, *constant_names) ⇒ Constant+

retrieve the constant spies from an object

Parameters:

  • base_module
  • constant_names

    *[Symbol]

Returns:



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/spy.rb', line 168

def get_const(base_module, *constant_names)
  if base_module.is_a?(Symbol)
    constant_names.unshift(base_module)
    base_module = Object
  end

  spies = constant_names.map do |constant_name|
    Constant.get(base_module, constant_name)
  end

  spies.size > 1 ? spies : spies.first
end

.mock(klass, *stubs) ⇒ Object

Create a mock object from a given class

Parameters:

  • klass (Class)

    class you wish to mock

  • stubs

    *[Symbol, Hash] methods you with to stub

Returns:

  • (Object)


122
123
124
125
126
127
128
# File 'lib/spy.rb', line 122

def mock(klass, *stubs)
  new_mock = Mock.new(klass).new
  if stubs.size > 0
    on(new_mock, *stubs)
  end
  new_mock
end

.mock_all(klass, *stubs) ⇒ Object

create a mock object from a given class with all the methods stubbed out and returning nil unless specified otherwise.

Parameters:

  • klass (Class)

    class you wish to mock

  • stubs

    *[Symbol, Hash] methods you with to stub

Returns:

  • (Object)


135
136
137
138
139
140
141
142
143
144
145
# File 'lib/spy.rb', line 135

def mock_all(klass, *stubs)
  mock_klass = Mock.new(klass)
  new_mock = mock_klass.new

  spies = stubs.size > 0 ? on(new_mock, *stubs) : []

  unstubbed_methods = mock_klass.mocked_methods - spies.map(&:method_name)
  on(new_mock, *unstubbed_methods) if unstubbed_methods.size > 0

  new_mock
end

.off(base_object, *method_names) ⇒ Subroutine+

removes the spy from the from the given object

Parameters:

  • base_object
  • method_names

    *[Symbol]

Returns:



32
33
34
35
36
37
38
39
40
41
# File 'lib/spy.rb', line 32

def off(base_object, *method_names)
  removed_spies = method_names.map do |method_name|
    spy = Subroutine.get(base_object, method_name)
    if spy
      spy.unhook
    end
  end

  removed_spies.size > 1 ? removed_spies : removed_spies.first
end

.off_const(base_module, *constant_names) ⇒ Constant+

removes stubs from given module

Parameters:

  • base_module (Module)
  • constant_names

    *[Symbol]

Returns:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/spy.rb', line 102

def off_const(base_module, *constant_names)
  if base_module.is_a?(Symbol)
    constant_names.unshift(base_module)
    base_module = Object
  end

  spies = constant_names.map do |constant_name|
    unless constant_name.is_a?(Symbol)
      raise ArgumentError, "#{constant_name.class} is an invalid input, #on only accepts Symbol, and Hash"
    end
    Constant.off(base_module, constant_name)
  end

  spies.size > 1 ? spies : spies.first
end

.off_instance_method(base_class, *method_names) ⇒ Spy

remove the stub from given Class

Parameters:

  • base_class (Class)
  • method_names

    *[Symbol]

Returns:



60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/spy.rb', line 60

def off_instance_method(base_class, *method_names)
  removed_spies = method_names.map do |method_name|
    spy = Subroutine.get(base_class, method_name, false)
    if spy
      spy.unhook
    else
      raise NoSpyError, "#{method_name} was not hooked on #{base_class.inspect}."
    end
  end

  removed_spies.size > 1 ? removed_spies : removed_spies.first
end

.on(base_object, *method_names) ⇒ Subroutine+

create a spy on given object

Parameters:

  • base_object
  • method_names

    *[Hash,Symbol] will spy on these methods and also set default return values

Returns:



20
21
22
23
24
25
26
# File 'lib/spy.rb', line 20

def on(base_object, *method_names)
  spies = method_names.map do |method_name|
    create_and_hook_spy(base_object, method_name)
  end.flatten

  spies.size > 1 ? spies : spies.first
end

.on_const(base_module, *constant_names) ⇒ Constant+

create a stub for constants on given module

Parameters:

  • base_module (Module)
  • constant_names

    *[Symbol, Hash]

Returns:



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/spy.rb', line 77

def on_const(base_module, *constant_names)
  if base_module.is_a?(Hash) || base_module.is_a?(Symbol)
    constant_names.unshift(base_module)
    base_module = Object
  end
  spies = constant_names.map do |constant_name|
    case constant_name
    when Symbol
      Constant.on(base_module, constant_name)
    when Hash
      constant_name.map do |name, result|
        Constant.on(base_module, name).and_return(result)
      end
    else
      raise ArgumentError, "#{constant_name.class} is an invalid input, #on only accepts Symbol, and Hash"
    end
  end.flatten

  spies.size > 1 ? spies : spies.first
end

.on_instance_method(base_class, *method_names) ⇒ Spy+

stubs the instance method of a given Class so all instance methods of this class will have the given method stubbed

Parameters:

  • base_class (Class)

    The class you wish to stub the instance methods of

  • method_names

    *[Symbol, Hash]

Returns:



48
49
50
51
52
53
54
# File 'lib/spy.rb', line 48

def on_instance_method(base_class, *method_names)
  spies = method_names.map do |method_name|
    create_and_hook_spy(base_class, method_name, false)
  end.flatten

  spies.size > 1 ? spies : spies.first
end

.teardownObject

unhook all methods



148
149
150
# File 'lib/spy.rb', line 148

def teardown
  Agency.instance.dissolve!
end