是否有可能在Lua中有条件地加载库?

时间:2017-06-07 17:00:28

标签: unit-testing lua

我正在制作mpv的脚本,并在其中加载mpv库,如下所示:

-- script.lua

local mp = require('mp')

我正在使用busted单元测试框架为此编写测试,它们包含在一个单独的文件中,如下所示:

-- script-tests.lua

describe('my script unit tests', function()
    local script = require('script')

    it('...', function()
        assert.is_true(true)
    end)
end)

当我运行单元测试时出现问题,我明白了:

./script.lua:1: module 'mp' not found:No LuaRocks module found for mp

我理解mp在我的脚本在mpv内运行时可用,但在我运行单元测试时则不行。有没有办法在运行单元测试时停止此require?或者我是以错误的方式思考这个问题?

解决方案

最后我创建了一个存根mp(尝试使用像Adam建议的全局标志,但它不起作用)。这是:

-- script.lua

local plugin = {}
local mpv_loaded, mp = pcall(require, 'mp')

plugin.mp = mp

---------------------------------------------------------------------
-- Stub MPV library for unit tests
if not mpv_loaded then
    plugin.mp = {}

    function plugin.mp.osd_message(message)
        plugin.mp.message = message
    end

    function plugin.mp.log(level, message)
        -- stub
    end

    function plugin.mp.add_forced_key_binding(...)
        -- stub
    end

    function plugin.mp.remove_key_binding(...)
        -- stub
    end
end

---------------------------------------------------------------------
-- Display message on screen.
function plugin:show_message(message)
    self.mp.osd_message(message)
end

return plugin

-- script-tests.lua

describe('my script unit tests', function()
    local plugin = require('script')

    it('...', function()
        message = 'It is better to play than do nothing.'
        plugin:show_message(message)

        assert.is_same(plugin.mp.message, message)
    end)

end)

2 个答案:

答案 0 :(得分:3)

您可以在单元测试中设置全局变量,并有条件地要求mp模块。

例如,在单元测试中,设置_UNITTEST变量:

-- script-tests.lua
_UNITTEST = true

describe('my script unit tests', function()
    local script = require('script')

    it('...', function()
        assert.is_true(true)
    end)
end)

然后,在你的脚本中:

-- script.lua
local mp = not _UNITTEST and require('mp')

Busted documentation中使用了类似的技术来公开测试的本地值。如果您需要测试依赖于mp模块的函数,那么您可能需要考虑提供stub实现。

答案 1 :(得分:2)

如果您关心的只是一个条件要求,那就意味着需要捕捉一条要求错误:

local mpv_loaded, mp = pcall(function() return require 'mp' end)

if not mpv_loaded then
    -- handle the bad require, in this case 'mp' holds the error message
else
    -- 'mp' contains the lib as it normally would
end