2012-10-01 43 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示波器:)非常感謝! –