使用package.preload来进行模拟一个lua模块。

我试图针对单个模块函数编写单元测试。这个模块与几个其他模块合作,因此我想模拟这些模块,以隔离我要测试的系统。这里是一些简化的伪代码:

local moduleFoo={}
local moduleBaz= require("moduleBaz")

moduleFoo.doSomething = function (arg)

  if moduleBaz.bar.neatMethod(arg) then
     --does something interesting
  end

end

return moduleFoo

这是moduleBaz的代码

local moduleBaz={}
moduleBaz.bar= {}

moduleBaz.bar.neatMethod=function(arg)
   --does something neat
end
return moduleBaz

我试图使用package.preload函数在我的测试运行之前注入模拟的moduleBaz实例,但似乎无效(即在测试中使用真实的模块Baz实例,而不是我的模拟实例)

这是一些伪测试代码:

    package.loaded.moduleBaz= nil
    local moduleBaz = {}
    moduleBaz.bar = {}
    moduleBaz.bar.neatMethod= function(guid) return true end

    package.preload['moduleBaz'] = function ()
        return moduleBaz
    end

   local foo= require("moduleFoo")
   foo.doSomething('asdasdasda')--调用了真实的moduleBaz,而不是我的模拟版本!

我做错了什么?我对Lua非常陌生,对于该语言中的范围处理方式不太熟悉!

点赞
用户1442917
用户1442917

你的 moduleBaz 代码似乎缺少了返回语句:

return moduleBaz

为什么不使用 package.loaded 呢?这会给你一个更简单的接口。package.loaded.moduleBaz 就只需要包含你想从你的 moduleBaz 代码返回的内容。像下面这样做或者给你提供一个思路:

package.loaded.moduleBaz = {
  bar = {
    neatmethod = function(arg)
      -- 你的模拟代码
    end,
  }
}

然后 require('moduleBaz') 就只会返回刚刚创建的那个对象了。

我无法复现你的问题。我使用的文件如下;请注意,我按照上面说的添加了 return moduleBaz,但这是我所做的唯一更改:

文件 moduleBaz.lua

local moduleBaz={}
moduleBaz.bar= {}
moduleBaz.bar.neatMethod=function(arg)
  print "baz"
  return true
end
return moduleBaz

文件 moduleFoo.lua

local moduleFoo={}
local moduleBaz=  require("moduleBaz")
moduleFoo.doSomething = function (arg)
  if moduleBaz.bar.neatMethod(arg) then
    print "foo"
  end
end
return moduleFoo

文件 testFoo.lua

package.loaded.moduleBaz= nil
local moduleBaz = {}
moduleBaz.bar = {}
moduleBaz.bar.neatMethod= function(guid) print "mock" return true end

package.preload['moduleBaz'] = function ()
    return moduleBaz
end

local foo= require("moduleFoo")
foo.doSomething('asdasdasda')--real moduleBaz is called, not my mock!

当我运行它时,我得到了预期的 mock\nfoo\n

2012-10-01 22:29:47