So the answer that I found after another day of debugging was that yes, you do need to use a table as the object that you call mock on. However, because lua is a very forgiving language when it comes to building objects with callable parameters this still ends up working. I've built a wrapper around the object for reasons unrelated to this question but you can see what I ultimately made work below.
function SessionConstructor.create(params)
local session_constructor = {}
setmetatable(session_constructor, SessionConstructor)
session_constructor.session = {}
session_constructor.session.params = params
session_constructor.session.getVariable = function(self,key)
return self.params[key]
end
session_constructor.session.setVariable = function(self, key, val)
self.params[key] = val
end
session_constructor.session.execute = function(self, cmd, code)
end
return session_constructor
end
function SessionConstructor:construct()
return self.session
end
One important caveat, because of how you have to pass self into functions that will be called with lua's ":" syntax the method of spying on what functions was called with does change as seen in test file below.
require "busted"
require "test_utils"
describe("Test voip lua script", function()
it('Test webrtc bad domain', function()
domain = 'rtc.baddomain.com';
session_params = {['sip_req_host'] = domain,
['sip_req_user'] = 'TEST-WebRTC-Client',
["sip_from_user"] = 'testwebrtc_p_12345',
['sip_call_id'] = 'test@call_id',
['sip_authorized'] = 'false'}
local sess_con = SessionConstructor.create(session_params)
exec_str = 'sofia_contact TEST-WebRTC-Client@'..domain;
local api_con = APIConstructor.create()
api_con:expect_exec(exec_str, 'error/user_not_registered')
_G.session = mock(sess_con:construct())
_G.api = mock(api_con:construct())
_G.freeswitch = create_freeswitch()
dofile("tested_script.lua")
assert.spy(session.execute).was.called_with(session, "respond", "407")
assert.spy(session.execute).was_not.called_with("respond", "407") --This is unfortunate
end)
end)