Как выполнить модульное тестирование модулей Lua без ОО? - PullRequest
0 голосов
/ 30 мая 2018

В Lua я могу написать простой модуль, подобный такому

local database = require 'database'
local M = {}

function M:GetData()
    return database:GetData()
end

return M

, который при необходимости будет загружаться один раз, и все будущие версии будут загружать одну и ту же копию.

Если бы я хотел использовать объектно-ориентированный подход, я мог бы сделать что-то вроде:

local M = {}
M.__index = M

function M:GetData() 
    return self.database:GetData()
end

return function(database)
    local newM = setmetatable({}, M)
    newM.database = database
    return newM
end

Где M загружается только один раз, и каждая копия newM просто содержит свои собственные данные и используетметоды оригинального M.

Когда дело доходит до тестирования, с помощью ОО-подхода я могу просто передать поддельную версию «базы данных» и проверить, что она вызывается, но с первым подходом я не могу.

Итак, мой вопрос: как я могу сделать так, чтобы первый подход поддерживал DI / тестирование, не делая его похожим на класс?

Я думал заключить его в замыкание примерно так:

local mClosure = function(database)
    local M = {}

    function M:GetData()
        return database:GetData()
    end

    return M
end

return mClosure

но затем каждый раз, когда он вызывается, он создает новую копию M, поэтому он теряет преимущества обоих предыдущих подходов.

1 Ответ

0 голосов
/ 31 мая 2018

Это очевидный пример использования библиотеки отладки Lua .При этом вы можете просто изменить значения вашей функции и ввести зависимости.Также учтите, что для этого вы можете использовать require;просто один раз потребуйте модуль базы данных, создайте небольшую таблицу, которая собирает данные, а затем перенаправляет на исходный модуль и помещает его в package.loaded, поэтому в следующий раз, когда вы его require, вызов require вернет измененную версию модуля.ОО-подход заключается в том, как вы могли бы делать подобные вещи на языке, подобном Ruby, но в Lua у нас есть более приятные способы подключения к модулю или функции без их специальной разработки.

local real_db = require 'db'
local fake_db = setmetatable({}, {__index=db})
fake_db.exec(query) print('running query: '..query) end -- dummy function
fake_db.something(...) print('doing something'); real_db.something(...) end
package.loaded.db = fake_db
require 'my_tests' -- this in turn requires 'db', but gets the fake one
package.loaded.db = real_db
-- After this point, `require 'db'` will return the original module
...