Имитация зависимостей в тестах
Заменяйте реальные реализации тестовыми дублями.
«Имитация зависимостей в тестах» — бесплатный урок Swift Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.
Имитация зависимостей в тестах
Имитация — это поддельная реализация зависимости, используемая в тестах. Поскольку мы внедряем протоколы, вместо настоящей зависимости можно передать имитацию.
Протокол для имитации
Начните с протокола, описывающего зависимость. Настоящий тип и имитация должны соответствовать ему.
protocol UserStore {
func name(for id: Int) -> String
}
struct RealStore: UserStore {
func name(for id: Int) -> String { "User-\(id)" }
}
print(RealStore().name(for: 5))Создание имитации
Имитация соответствует протоколу, но возвращает заранее заданные значения, избегая настоящего доступа к сети или диску.
protocol UserStore { func name(for id: Int) -> String }
struct MockStore: UserStore {
func name(for id: Int) -> String { "Mock" }
}
print(MockStore().name(for: 99))Внедрение имитации
Передайте имитацию тестируемой системе через её инициализатор. Код, который вы тестируете, не сможет отличить её от настоящей зависимости.
protocol UserStore { func name(for id: Int) -> String }
struct MockStore: UserStore { func name(for id: Int) -> String { "Mock" } }
struct Profile {
let store: UserStore
func title(_ id: Int) -> String { "Hello, " + store.name(for: id) }
}
print(Profile(store: MockStore()).title(1))Запись вызовов
Имитация может записывать сведения о своём использовании, чтобы тест мог проверить корректность вызова зависимости.
protocol Analytics { func track(_ e: String) }
class SpyAnalytics: Analytics {
var events: [String] = []
func track(_ e: String) { events.append(e) }
}
let spy = SpyAnalytics()
spy.track("open")
spy.track("buy")
print(spy.events)Проверка поведения
После выполнения кода проверьте записанные данные. Здесь мы проверяем, что было отправлено правильное событие.
protocol Analytics { func track(_ e: String) }
class Spy: Analytics { var last = ""; func track(_ e: String) { last = e } }
struct Checkout { let analytics: Analytics; func pay() { analytics.track("paid") } }
let spy = Spy()
Checkout(analytics: spy).pay()
print(spy.last == "paid")Подстановка возвращаемых значений
Заглушка возвращает заранее заданные значения, чтобы можно было проверить реакцию кода на определённые входные данные.
protocol Clock { func hour() -> Int }
struct StubClock: Clock { let value: Int; func hour() -> Int { value } }
struct Greeter { let clock: Clock; func greet() -> String { clock.hour() < 12 ? "AM" : "PM" } }
print(Greeter(clock: StubClock(value: 9)).greet())
print(Greeter(clock: StubClock(value: 18)).greet())Имитация сбоя
Имитации могут воспроизводить состояния ошибок, которые трудно вызвать с настоящими зависимостями, повышая охват тестами.
protocol Loader { func load() -> Int? }
struct FailingLoader: Loader { func load() -> Int? { nil } }
struct VM { let loader: Loader; func status() -> String { loader.load() == nil ? "error" : "ok" } }
print(VM(loader: FailingLoader()).status())Детерминированные тесты
Поскольку имитации возвращают фиксированные значения, тесты выполняются быстро и детерминированно, без нестабильности настоящих сервисов.
protocol Random { func next() -> Int }
struct FixedRandom: Random { func next() -> Int { 42 } }
struct Game { let rng: Random; func roll() -> Int { rng.next() } }
print(Game(rng: FixedRandom()).roll())Здесь нет фреймворка для тестирования
В настоящем проекте эти проверки выполнялись бы с помощью утверждений XCTest. Подход с внедрением остаётся тем же, меняется только синтаксис проверки.
protocol Calc { func add(_ a: Int, _ b: Int) -> Int }
struct RealCalc: Calc { func add(_ a: Int, _ b: Int) -> Int { a + b } }
struct MockCalc: Calc { func add(_ a: Int, _ b: Int) -> Int { 0 } }
print(RealCalc().add(2, 2))
print(MockCalc().add(2, 2))Полный цикл
Определите протокол, создайте настоящую реализацию и имитацию, внедрите имитацию, выполните тестируемый код и проверьте результат. DI делает возможным каждый из этих шагов.
protocol Repo { func count() -> Int }
struct MockRepo: Repo { func count() -> Int { 3 } }
struct Stats { let repo: Repo; func total() -> Int { repo.count() * 2 } }
print(Stats(repo: MockRepo()).total())Быстрая проверка
Что делает возможной имитацию зависимости в этом подходе?
Итоги
Имитация соответствует внедрённому протоколу и возвращает заранее заданные значения, записывает вызовы или воспроизводит сбои. Её внедрение обеспечивает быстрые и детерминированные тесты. Цикл выглядит так: определить протокол, создать настоящую реализацию и имитацию, внедрить её, выполнить код и проверить результат. На этом курс DI завершён.
Изучай Swift с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 122
- Уроки
- 409
Часто задаваемые вопросы
Урок «Имитация зависимостей в тестах» бесплатный?
Да — полный текст урока «Имитация зависимостей в тестах» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.
Чему я научусь в уроке «Имитация зависимостей в тестах»?
Заменяйте реальные реализации тестовыми дублями. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Имитация зависимостей в тестах»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Зачем нужна инъекция зависимостей
- Инъекция через конструктор
- Абстракции на основе протоколов
- Имитация зависимостей в тестах