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

我知道当我的脚本在 mpv 中运行时 mp 是可用的,但在运行单元测试时不可用。是否有方法在运行单元测试时停止这个 require 呢?或者我的想法错了吗?

解决方案

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

-- script.lua

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

plugin.mp = mp

---------------------------------------------------------------------
-- 用于单元测试的 MPV 库桩
if not mpv_loaded then
    plugin.mp = {}

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

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

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

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

---------------------------------------------------------------------
-- 在屏幕上显示消息。
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)
点赞
用户415823
用户415823

你可以在单元测试中设置一个全局变量,并有条件地要求 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 文档 中使用了类似的技术来公开本地值以供测试。如果你需要测试依赖于 mp 模块的函数,那么你可能需要考虑提供一个 存根(stub) 实现。

2017-06-07 18:05:51
用户6614127
用户6614127

如果你关心的仅仅是一个条件性的 require,也就是说捕捉 require 错误:

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

if not mpv_loaded then
    -- 处理错误的 require,在这种情况下,'mp' 包含了错误信息
else
    -- 'mp' 包含了正常的库文件
end
2017-06-07 22:48:22