2012-10-01 44 views
2

我正在尝试针对单个模块函数编写单元测试。该模块与其他几个模块协作,所以我想模拟这些模块来隔离我的系统。下面是一些简单的伪代码:使用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

我试图使用package.preload功能我的测试运行之前注入moduleBaz的模拟实例的代码
local moduleBaz={} 
moduleBaz.bar= {} 

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

,但它似乎并没有工作(即moduleBaz的真实实例测试,不是我的模拟使用)

下面是一些psueudo测试代码:

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非常陌生,对于如何在语言中处理范围感到不太舒服!

+0

你是否也在'package.loaded.moduleFoo = nil'确定你没有使用旧版本的moduleFoo? –

+0

我确实尝试过。它似乎没有效果,因为package.preload永远不会被调用。 –

回答

4

你似乎缺少一个return语句在moduleBaz代码

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! 

当我运行这个,我得到按预期打印。

+0

我的实际代码确实包含了一个return语句。但是,您的回答告诉我执行顺序很重要。也就是说,在通过require加载moduleFoo之前​​,我没有连接package.preload。回想起来,这很有道理。在相关说明中,我不能强制我的模拟moduleBaz卸载使用package.loaded.moduleBaz = nil。我想在每次测试后卸载它,以便下一个测试可以“干净地”运行。我希望这与foo的范围有关(我声明它是全局的),并且只要foo在范围内,Lua就不会允许我卸载moduleBaz? –

+1

@Dirk:有两件事在玩。设置'package.loaded.moduleBaz'不会对已经由该模块加载的代码执行任何操作;它只是允许你再次执行“require”(没有设置就是nil它只会返回'package.loaded.moduleBaz'的值)。如果您想“卸载”它,您仍然需要重置模块已经填充的任何其他变量。尝试将'foo'设置为零。 –

+0

将foo设置为零就行了。我仍然习惯于Lua示波器:)非常感谢! –