Skip to content

Commit ca48966

Browse files
committed
Merge branch 'master' of github.com:ryanplusplus/mock.lua
Conflicts: mock.lua
2 parents 6b9ab2f + 21eab1d commit ca48966

File tree

2 files changed

+52
-17
lines changed

2 files changed

+52
-17
lines changed

mock.lua

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ local Mock = {}
22

33
local subscriber
44

5-
local function mockHandle(callback, thunk)
5+
function mockHandle(callback, thunk)
66
subscriber = callback
77
thunk()
88
subscriber = nil
99
end
1010

11-
local function mockCalled(m, name, args)
11+
function mockCalled(m, name, args)
1212
return subscriber(m, name, args)
1313
end
1414

@@ -115,9 +115,9 @@ function MockExpectation:when(thunk)
115115
end
116116

117117
if not validFunctionFound then
118-
error('unexpected function "' .. name .. '" called', 2)
118+
error('unexpected function call ' .. name .. '(' .. table.concat(args, ', ') .. ')', 2)
119119
else
120-
error('unexpected arguments provided to function "' .. name .. '"', 2)
120+
error('unexpected arguments provided to function ' .. name, 2)
121121
end
122122
end
123123

@@ -202,34 +202,43 @@ end
202202

203203
function Mock:mockFunction(name)
204204
name = name or '<anonymous>'
205-
local f
205+
local f = {}
206206

207-
function f(...)
207+
function fCall(_, ...)
208208
return mockCalled(f, name, table.pack(...))
209209
end
210210

211+
setmetatable(f, {__call = fCall})
212+
211213
return f
212214
end
213215

214216
function Mock:mockMethod(name)
215217
name = name or '<anonymous>'
216-
local m
218+
local m = {}
217219

218-
function m(...)
220+
function mCall(_, _, ...)
219221
local args = table.pack(...)
220-
table.remove(args, 1)
221222
return mockCalled(m, name, args)
222223
end
223224

225+
setmetatable(m, {__call = mCall})
226+
224227
return m
225228
end
226229

230+
function IsCallable(x)
231+
local isFunction = type(x) == 'function'
232+
local hasCallMetamethod = type((debug.getmetatable(x) or {}).__call) == 'function'
233+
return isFunction or hasCallMetamethod
234+
end
235+
227236
function Mock:mockTable(t, name)
228237
name = name or '<anonymous>'
229238
local mocked = {}
230239

231240
for k, v in pairs(t) do
232-
if type(v) == 'function' then
241+
if IsCallable(v) then
233242
mocked[k] = self:mockFunction(name .. '.' .. tostring(k))
234243
end
235244
end
@@ -242,7 +251,7 @@ function Mock:mockObject(o, name)
242251
local mocked = {}
243252

244253
for k, v in pairs(o) do
245-
if type(v) == 'function' then
254+
if IsCallable(v) then
246255
mocked[k] = self:mockMethod(name .. ':' .. tostring(k))
247256
end
248257
end

spec/mock_spec.lua

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('The mock library', function()
2828
it('should alert you when a function is not called', function()
2929
local f = mock:mockFunction('f')
3030

31-
shouldFail(function()
31+
shouldFailWith('not all calls occurred', function()
3232
mock(f):shouldBeCalled():
3333
when(function() end)
3434
end)
@@ -38,7 +38,7 @@ describe('The mock library', function()
3838
local f1 = mock:mockFunction('f1')
3939
local f2 = mock:mockFunction('f2')
4040

41-
shouldFailWith('unexpected function "f2" called', function()
41+
shouldFailWith('unexpected function call f2()', function()
4242
mock(f1):shouldBeCalled():
4343
when(function() f2() end)
4444
end)
@@ -47,7 +47,7 @@ describe('The mock library', function()
4747
it('should alert you when a function is called unexpectedly', function()
4848
local f = mock:mockFunction('f')
4949

50-
shouldFailWith('unexpected function "f" called', function()
50+
shouldFailWith('unexpected function call f()', function()
5151
f()
5252
end)
5353
end)
@@ -194,6 +194,32 @@ describe('The mock library', function()
194194
end)
195195
end)
196196

197+
it('should allow mocking of any callable in an object, not just functions', function()
198+
local someTable = {
199+
foo = {}
200+
}
201+
202+
setmetatable(someTable.foo, {__call = function() end})
203+
204+
local mockedTable = mock:mockTable(someTable)
205+
206+
mock(mockedTable.foo):shouldBeCalled():
207+
when(function() mockedTable.foo() end)
208+
end)
209+
210+
it('should allow mocking of any callable in a table, not just functions', function()
211+
local someObject = {
212+
foo = {}
213+
}
214+
215+
setmetatable(someObject.foo, {__call = function() end})
216+
217+
local mockedObject = mock:mockObject(someObject)
218+
219+
mock(mockedObject.foo):shouldBeCalled():
220+
when(function() mockedObject:foo() end)
221+
end)
222+
197223
it('should fail when a method is incorrectly used as a function', function()
198224
shouldFail(function()
199225
local someObject = {}
@@ -307,7 +333,7 @@ describe('The mock library', function()
307333
local f1 = mock:mockFunction('f1')
308334
local f2 = mock:mockFunction('f2')
309335

310-
shouldFailWith('unexpected function "f2" called', function()
336+
shouldFailWith('unexpected function call f2()', function()
311337
mock(f1):shouldBeCalled():
312338
andThen(mock(f2):shouldBeCalled()):
313339
when(function()
@@ -316,7 +342,7 @@ describe('The mock library', function()
316342
end)
317343
end)
318344

319-
shouldFailWith('unexpected arguments provided to function "f1"', function()
345+
shouldFailWith('unexpected arguments provided to function f1', function()
320346
mock(f1):shouldBeCalledWith(1):
321347
andThen(mock(f2):shouldBeCalled(2)):
322348
when(function()
@@ -331,7 +357,7 @@ describe('The mock library', function()
331357
local f2 = mock:mockFunction('f2')
332358
local f3 = mock:mockFunction('f3')
333359

334-
shouldFailWith('unexpected function "f3" called', function()
360+
shouldFailWith('unexpected function call f3()', function()
335361
mock(f1):shouldBeCalled():
336362
andAlso(mock(f2):shouldBeCalled()):
337363
andThen(mock(f3):shouldBeCalled()):

0 commit comments

Comments
 (0)