-
-
Notifications
You must be signed in to change notification settings - Fork 156
/
mockery.rb
241 lines (195 loc) · 6.73 KB
/
mockery.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
require 'mocha/ruby_version'
require 'mocha/central'
require 'mocha/mock'
require 'mocha/names'
require 'mocha/receivers'
require 'mocha/state_machine'
require 'mocha/logger'
require 'mocha/configuration'
require 'mocha/stubbing_error'
require 'mocha/not_initialized_error'
require 'mocha/expectation_error_factory'
module Mocha
class Mockery
class Null < self
def add_mock(*)
raise_not_initialized_error
end
def add_state_machine(*)
raise_not_initialized_error
end
def stubba
Central::Null.new(&method(:raise_not_initialized_error))
end
private
def raise_not_initialized_error
message = 'Mocha methods cannot be used outside the context of a test'
raise NotInitializedError.new(message, caller)
end
end
class << self
def instance
instances.last || Null.new
end
def setup
mockery = new
mockery.logger = instance.logger unless instances.empty?
@instances.push(mockery)
end
def verify(*args)
instance.verify(*args)
end
def teardown
instance.teardown
ensure
@instances.pop
@instances = nil if instances.empty?
end
private
def instances
@instances ||= []
end
end
def named_mock(name, &block)
add_mock(Mock.new(self, Name.new(name), &block))
end
def unnamed_mock(&block)
add_mock(Mock.new(self, &block))
end
def mock_impersonating(object, &block)
add_mock(Mock.new(self, ImpersonatingName.new(object), ObjectReceiver.new(object), &block))
end
def mock_impersonating_any_instance_of(klass, &block)
add_mock(Mock.new(self, ImpersonatingAnyInstanceName.new(klass), AnyInstanceReceiver.new(klass), &block))
end
def new_state_machine(name)
add_state_machine(StateMachine.new(name))
end
def verify(assertion_counter = nil)
unless mocks.all? { |mock| mock.__verified__?(assertion_counter) }
message = "not all expectations were satisfied\n#{mocha_inspect}"
if unsatisfied_expectations.empty?
backtrace = caller
else
backtrace = unsatisfied_expectations[0].backtrace
end
raise ExpectationErrorFactory.build(message, backtrace)
end
expectations.each do |e|
unless Mocha::Configuration.allow?(:stubbing_method_unnecessarily)
unless e.used?
on_stubbing_method_unnecessarily(e)
end
end
end
end
def teardown
stubba.unstub_all
reset
end
def stubba
@stubba ||= Central.new
end
def mocks
@mocks ||= []
end
def state_machines
@state_machines ||= []
end
def mocha_inspect
message = ""
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map { |e| e.mocha_inspect }.join("\n- ")}\n" unless unsatisfied_expectations.empty?
message << "satisfied expectations:\n- #{satisfied_expectations.map { |e| e.mocha_inspect }.join("\n- ")}\n" unless satisfied_expectations.empty?
message << "states:\n- #{state_machines.map { |sm| sm.mocha_inspect }.join("\n- ")}" unless state_machines.empty?
message
end
def on_stubbing(object, method)
method = PRE_RUBY_V19 ? method.to_s : method.to_sym
unless Mocha::Configuration.allow?(:stubbing_non_existent_method)
unless object.method_exists?(method, include_public_methods = true)
on_stubbing_non_existent_method(object, method)
end
end
unless Mocha::Configuration.allow?(:stubbing_non_public_method)
if object.method_exists?(method, include_public_methods = false)
on_stubbing_non_public_method(object, method)
end
end
unless Mocha::Configuration.allow?(:stubbing_method_on_nil)
if object.nil?
on_stubbing_method_on_nil(object, method)
end
end
unless Mocha::Configuration.allow?(:stubbing_method_on_non_mock_object)
on_stubbing_method_on_non_mock_object(object, method)
end
end
def on_stubbing_non_existent_method(object, method)
if Mocha::Configuration.prevent?(:stubbing_non_existent_method)
raise StubbingError.new("stubbing non-existent method: #{object.mocha_inspect}.#{method}", caller)
end
if Mocha::Configuration.warn_when?(:stubbing_non_existent_method)
logger.warn "stubbing non-existent method: #{object.mocha_inspect}.#{method}"
end
end
def on_stubbing_non_public_method(object, method)
if Mocha::Configuration.prevent?(:stubbing_non_public_method)
raise StubbingError.new("stubbing non-public method: #{object.mocha_inspect}.#{method}", caller)
end
if Mocha::Configuration.warn_when?(:stubbing_non_public_method)
logger.warn "stubbing non-public method: #{object.mocha_inspect}.#{method}"
end
end
def on_stubbing_method_on_nil(object, method)
if Mocha::Configuration.prevent?(:stubbing_method_on_nil)
raise StubbingError.new("stubbing method on nil: #{object.mocha_inspect}.#{method}", caller)
end
if Mocha::Configuration.warn_when?(:stubbing_method_on_nil)
logger.warn "stubbing method on nil: #{object.mocha_inspect}.#{method}"
end
end
def on_stubbing_method_on_non_mock_object(object, method)
if Mocha::Configuration.prevent?(:stubbing_method_on_non_mock_object)
raise StubbingError.new("stubbing method on non-mock object: #{object.mocha_inspect}.#{method}", caller)
end
if Mocha::Configuration.warn_when?(:stubbing_method_on_non_mock_object)
logger.warn "stubbing method on non-mock object: #{object.mocha_inspect}.#{method}"
end
end
def on_stubbing_method_unnecessarily(expectation)
if Mocha::Configuration.prevent?(:stubbing_method_unnecessarily)
raise StubbingError.new("stubbing method unnecessarily: #{expectation.method_signature}", expectation.backtrace)
end
if Mocha::Configuration.warn_when?(:stubbing_method_unnecessarily)
logger.warn "stubbing method unnecessarily: #{expectation.method_signature}"
end
end
attr_writer :logger
def logger
@logger ||= Logger.new($stderr)
end
private
def expectations
mocks.map { |mock| mock.__expectations__.to_a }.flatten
end
def unsatisfied_expectations
expectations.reject { |e| e.verified? }
end
def satisfied_expectations
expectations.select { |e| e.verified? }
end
def add_mock(mock)
mocks << mock
mock
end
def add_state_machine(state_machine)
state_machines << state_machine
state_machine
end
def reset
@stubba = nil
@mocks = nil
@state_machines = nil
end
end
end