Имитации и шпионы
Изолируйте проверяемый код.
«Имитации и шпионы» — бесплатный урок Lua Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Тестовые двойники
Иногда функция зависит от чего-то медленного или внешнего, например от сетевого вызова или регистратора. Тестовые двойники заменяют такие зависимости управляемыми заменителями.
busted предоставляет три вида двойников: шпионы, заглушки и моки. Каждый из них решает свою задачу.
Что делает spy
spy оборачивает функцию и записывает сведения о её вызовах, продолжая выполнять исходную функцию. Это позволяет проверить, что функция была вызвана.
Создайте spy с помощью spy.new вокруг функции или установите его для поля таблицы.
local s = spy.new(function() end)
s(1, 2)
assert.spy(s).was.called()Наблюдение за методом
Используйте spy.on, чтобы отслеживать метод существующей таблицы. Исходный метод продолжает выполняться, а busted отслеживает каждый вызов.
Это идеально подходит для проверки побочного эффекта, например вызова регистратора.
spy.on(logger, "info")
service.run()
assert.spy(logger.info).was.called()Проверка количества вызовов
Шпионы записывают, сколько раз их вызвали. Используйте was.called(n), чтобы проверить точное количество вызовов.
Это помогает обнаружить ошибки, при которых функция вызывается слишком часто или не вызывается вовсе.
assert.spy(s).was.called(2)
assert.spy(s).was_not.called()Проверка аргументов вызова
С помощью was.called_with можно проверить, какие аргументы получил spy. busted сравнивает записанные аргументы с ожидаемыми.
Так Вы проверяете не только то, что функция выполнилась, но и то, что она выполнилась правильно.
local s = spy.new(function() end)
s("user", 42)
assert.spy(s).was.called_with("user", 42)Что делает stub
stub полностью заменяет функцию, поэтому исходная функция никогда не выполняется. Используйте его, чтобы пропустить медленную или нежелательную работу, например настоящий сетевой доступ или доступ к диску.
Создайте его с помощью stub для поля таблицы. По умолчанию заглушка ничего не делает и возвращает nil.
stub(api, "fetch")
service.load()
assert.stub(api.fetch).was.called()Возвращаемые значения stub
С помощью returns можно заставить stub возвращать фиксированное значение. Так в проверяемый код поступают управляемые данные.
Теперь Ваша проверка вообще не зависит от настоящей зависимости.
stub(api, "fetch").returns({id = 1})
local r = service.load()
assert.are.same({id = 1}, r)Что делает mock
mock принимает существующую таблицу и сразу превращает все её функции в шпионы или заглушки. Это удобный способ отслеживать целый объект.
Вызовите mock(obj), чтобы обернуть объект, а затем выполняйте проверки отдельных методов.
local m = mock(realLogger)
app.start(m)
assert.spy(m.warn).was.called()Mock с методами-заглушками
Если передать true вторым аргументом в mock, каждый метод будет заменён заглушкой, поэтому исходные методы не выполнятся. Это полностью изолирует объект.
Используйте такой подход, когда побочные эффекты настоящих методов необходимо исключить.
local db = mock(database, true)
db.query.returns({})
assert.are.same({}, repo.all())Восстановление двойников
Шпионы, заглушки и моки изменяют общие таблицы, поэтому их необходимо восстановить, иначе последующие тесты увидят двойник. Вызовите :revert() или mock.revert.
Разместите восстановление в after_each, чтобы гарантировать чистое состояние между тестами.
after_each(function()
mock.revert(m)
end)Выбор подходящего двойника
Используйте spy, чтобы наблюдать за настоящей функцией, stub — чтобы заменить её управляемым поведением, а mock — чтобы сразу обернуть целый объект.
Выбирайте самый простой двойник, решающий задачу. Избыточное использование моков может сделать тесты хрупкими и скрыть настоящие ошибки.
describe("mailer", function()
it("sends once", function()
local s = spy.on(smtp, "send")
mailer.notify("a@b.com")
assert.spy(s).was.called(1)
end)
end)Быстрая проверка
Проверьте, насколько Вы поняли тестовые двойники busted.
Итоги
Тестовые двойники изолируют код от медленных или внешних зависимостей. spy записывает вызовы, выполняя исходную функцию, stub заменяет функцию управляемым поведением, а mock оборачивает целый объект.
Выполняйте проверки с помощью was.called и was.called_with, а затем всегда восстанавливайте двойники с помощью revert в after_each, чтобы тесты оставались изолированными.
Часто задаваемые вопросы
Урок «Имитации и шпионы» бесплатный?
Да — полный текст урока «Имитации и шпионы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Имитации и шпионы»?
Изолируйте проверяемый код. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Имитации и шпионы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Зачем нужны тесты
- Блоки describe и it
- Проверки утверждений
- Имитации и шпионы