I am trying to unit test code using Busted (which I did not write, nor am I allowed to refactor at this time for business reasons) in Lua, and there is no concept in this module of classes nor dependency injection. So, I'd like to replace some of the modules required at the top of the file, i.e local log = require("path.to.module.logger"):new()
with a mocked logger that I made to track the number of times methods are called, i.e logger:trace()
such as with times()
in Mockito in Java. In Java, I can use Reflection.Utils for this purpose. What's the equivalent in Lua to help make this not-testable code, testable?
I've already tried creating a global variable with the same variable name log
and setting it equal to my mock using this example: https://www.lua.org/pil/14.2.html
local _M = {}
local log = require("path.to.module.logger"):new()
...
function _M.init(...) log:trace("debug") # I would like this log instance to not be the one above, rather the one I inject into the module at runtime end
I was actually able to find an answer this morning from a colleague. "Reflection" is not really possible, as Nicol Bolas suggested in his answer, however, from the lua documentation (http://lua-users.org/wiki/ModulesTutorial), we learn that:
Lua caches modules in the package.loaded table.
That means we can overwrite the package.loaded
table in our busted test and essentially, at runtime, replace dependencies in tightly coupled code (much like mocking in Mockito via dependency injection in Java). For example:
package.loaded["path.to.module.logger"] = my_logger
would replace the dependency path.to.module.logger
globally with my_logger
assuming it adhered to the same contract.