【问题标题】:mocking out a lua module using package.preload使用 package.preload 模拟一个 lua 模块
【发布时间】:2012-10-01 15:49:49
【问题描述】:

我正在尝试针对单个模块功能编写单元测试。该模块与其他一些模块协作,因此我想模拟这些模块以隔离我的测试系统。下面是一些简化的伪代码:

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 的模拟实例,但它似乎不起作用(即在测试中使用了 moduleBaz 的真实实例,而不是我的模拟)

这是一些伪测试代码:

    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')--real moduleBaz is called, not my mock!

任何想法我做错了什么?我对 Lua 很陌生,对语言中如何处理范围完全不满意!

【问题讨论】:

  • 您是否也在使用package.loaded.moduleFoo= nil 以确保您没有使用旧版本的moduleFoo?
  • 我确实尝试过。它似乎没有任何效果,因为 package.preload 从未被调用过。

标签: lua mocking


【解决方案1】:

您的 moduleBaz 代码中似乎缺少 return 语句

return moduleBaz

为什么不使用package.loaded,因为它为您提供了更简单的界面? package.loaded.moduleBaz 只需要包含您想要从 moduleBaz 代码返回的任何内容。像这样的东西应该可以工作或给你一个想法:

package.loaded.moduleBaz = {
  bar = {
    neatmethod = function(arg)
      -- your mock code here
    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

【讨论】:

  • 我的实际代码确实包含了一个返回语句。但是,您的回答告诉我执行顺序很重要。也就是说,在通过 require 加载 moduleFoo 之前,我没有连接 package.preload。回想起来,这完全有道理。在相关说明中,我无法使用 package.loaded.moduleBaz = nil 强制我的模拟 moduleBaz 卸载。我想在每次测试后卸载它,以便下一个测试可以“干净地”运行。我希望这与 foo 的范围有关(我将其声明为全局),并且只要 foo 在范围内,Lua 就不允许我卸载 moduleBaz?
  • @Dirk:有两件事在起作用。设置package.loaded.moduleBaz 不会对该模块已经加载的代码做任何事情;它只允许您再执行一次“require”(如果没有设置为 nil,它只会返回 package.loaded.moduleBaz 的值)。如果你想“卸载”它,你仍然需要重置模块填充的任何其他变量。尝试将foo 设置为零。
  • 将 foo 设置为 nil 就可以了。我还在习惯 Lua 范围 :) 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多