-- module will return a stub module table local assert = require 'luassert.assert' local spy = require 'luassert.spy' local util = require 'luassert.util' local unpack = util.unpack local pack = util.pack local stub = {} function stub.new(object, key, ...) if object == nil and key == nil then -- called without arguments, create a 'blank' stub object = {} key = "" end local return_values = pack(...) assert(type(object) == "table" and key ~= nil, "stub.new(): Can only create stub on a table key, call with 2 params; table, key", util.errorlevel()) assert(object[key] == nil or util.callable(object[key]), "stub.new(): The element for which to create a stub must either be callable, or be nil", util.errorlevel()) local old_elem = object[key] -- keep existing element (might be nil!) local fn = (return_values.n == 1 and util.callable(return_values[1]) and return_values[1]) local defaultfunc = fn or function() return unpack(return_values) end local oncalls = {} local callbacks = {} local stubfunc = function(...) local args = util.make_arglist(...) local match = util.matchoncalls(oncalls, args) if match then return callbacks[match](...) end return defaultfunc(...) end object[key] = stubfunc -- set the stubfunction local s = spy.on(object, key) -- create a spy on top of the stub function local spy_revert = s.revert -- keep created revert function s.revert = function(self) -- wrap revert function to restore original element if not self.reverted then spy_revert(self) object[key] = old_elem self.reverted = true end return old_elem end s.returns = function(...) local return_args = pack(...) defaultfunc = function() return unpack(return_args) end return s end s.invokes = function(func) defaultfunc = function(...) return func(...) end return s end s.by_default = { returns = s.returns, invokes = s.invokes, } s.on_call_with = function(...) local match_args = util.make_arglist(...) match_args = util.copyargs(match_args) return { returns = function(...) local return_args = pack(...) table.insert(oncalls, match_args) callbacks[match_args] = function() return unpack(return_args) end return s end, invokes = function(func) table.insert(oncalls, match_args) callbacks[match_args] = function(...) return func(...) end return s end } end return s end local function set_stub(state, arguments) state.payload = arguments[1] state.failure_message = arguments[2] end assert:register("modifier", "stub", set_stub) return setmetatable(stub, { __call = function(self, ...) -- stub originally was a function only. Now that it is a module table -- the __call method is required for backward compatibility return stub.new(...) end })