lualua-5.1

How can I use reflection (at runtime) in Lua?


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


Solution

  • 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.