Я новичок в Lua. Я тестирую модуль Lua 5.1 с использованием Lunity и LeMock.Взаимодействие зависимостей Lua I/O
Мой класс - StorageManager. Я тестирую модуль методом load(), который загружает файлы с диска. Я не хочу, чтобы мои модульные тесты зависели от фактических файлов на реальном диске, чтобы проверить это.
Итак, я пытаюсь ввести зависимость ввода-вывода с макетным объектом и проверить поведение объекта во время моего теста. Я не могу понять, как использовать объект ввода-вывода с синтаксисом, который работает, когда вызывается как моим модульным модульным тестом, так и «реальным кодом».
Как я могу изменить код (метод load(), желательно), чтобы он выполнял свою работу при вызове из одного модульного теста (один без макета является временным, пока я не получу этот результат - он напоминает код, который позже на самом деле вызовет тестируемый метод)?
Примечание1: Если вы запустите эти тесты, помните, что тест «без макета» ожидает файл на диске, имя файла которого соответствует VALID_FILENAME.
Note2: Я думал об использовании поведения try/catch-like pcall для выполнения одной строки или другой строки (см. Строки storageManager.lua 11 & 12). Предполагая, что это даже возможно, это похоже на взлом, и он ловушки ошибок, которые я мог бы позже захотеть выбросить (из-за нагрузки()). Пожалуйста, изложите эту опцию, если вы не видите альтернативы.
test_storageManager.lua:
1 require "StorageManager"
2 require "lunity"
3 require "lemock"
4 module("storageManager", package.seeall, lunity)
5
6 VALID_FILENAME = "storageManagerTest.dat"
7
8 function setup()
9 mc = lemock.controller()
10 end
11
12 function test_load_reads_file_properly()
13 io_mock = mc:mock()
14 file_handle_mock = mc:mock()
15 io_mock:open(VALID_FILENAME, "r");mc:returns(file_handle_mock)
16 file_handle_mock:read("*all")
17 file_handle_mock:close()
18 mc:replay()
19 storageManager = StorageManager:new{ io = io_mock }
20 storageManager:load(VALID_FILENAME)
21 mc:verify()
22 end
23
24 function test_load_reads_file_properly_without_mock()
25 storageManager = StorageManager:new()
26 storageManager:load(VALID_FILENAME)
27 end
28
29 runTests{useANSI = false}
storageManager.lua:
1 StorageManager = {}
2
3 function StorageManager.new (self,init)
4 init = init or { io=io } -- I/O dependency injection attempt
5 setmetatable(init,self)
6 self.__index = self
7 return init
8 end
9
10 function StorageManager:load(filename)
11 file_handle = self['io'].open(self['io'], filename, "r") -- works w/ mock
12 -- file_handle = io.open(filename, "r") -- works w/o mock
13 result = file_handle:read("*all")
14 file_handle:close()
15 return result
16 end
Edit:
Эти классы проходят оба теста. Огромное спасибо RBerteig.
test_storageManager.lua
1 require "admin.StorageManager"
2 require "tests.lunity"
3 require "lib.lemock"
4 module("storageManager", package.seeall, lunity)
5
6 VALID_FILENAME = "storageManagerTest.dat"
7
8 function setup()
9 mc = lemock.controller()
10 end
11
12 function test_load_reads_file_properly()
13 io_mock = mc:mock()
14 file_handle_mock = mc:mock()
15 io_mock.open(VALID_FILENAME, "r");mc:returns(file_handle_mock)
16 file_handle_mock:read("*all")
17 file_handle_mock:close()
18 mc:replay()
19 local saved_io = _G.io
20 _G.io = io_mock
21 package.loaded.io = io_mock
22 storageManager = StorageManager:new()
23 storageManager:load(VALID_FILENAME)
24 _G.io = saved_io
25 package.loaded.io = saved_io
26 mc:verify()
27 end
28
29 function test_load_reads_file_properly_without_mock()
30 storageManager = StorageManager:new()
31 storageManager:load(VALID_FILENAME)
32 end
33
34 runTests{useANSI = false}
storageManager.lua
1 StorageManager = {}
2
3 function StorageManager.new (self,init)
4 init = init or {}
5 setmetatable(init,self)
6 self.__index = self
7 return init
8 end
9
10 function StorageManager:load(filename)
11 file_handle = io.open(filename, "r")
12 result = file_handle:read("*all")
13 file_handle:close()
14 return result
15 end
Я не имею в виду (или не знаю, как) «локализовать объект io для производительности», но я хочу «заменить глобальный io на [мой] макет объекта при запуске теста». Я думал, что делаю это на storageManager.lua: 4? Как правильно «заменить глобальную io»? Можете ли вы предоставить пример кода (или указать мне)? – lance
Ваше редактирование дало мне то, что мне было нужно. Я редактировал измененный код в исходный вопрос. Большое спасибо. – lance