Тестирование моделей представления
Тестируйте логику представления изолированно.
«Тестирование моделей представления» — бесплатный урок Swift Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.
Зачем тестировать ViewModel
ViewModel содержит логику представления, поэтому это наиболее ценное для модульного тестирования звено. Поскольку оно не зависит от UIKit или SwiftUI, его можно быстро и детерминированно тестировать изолированно.
Спроектировано для тестирования
Хорошо спроектированный ViewModel получает зависимости через свой инициализатор. Благодаря этому тесты могут подставлять имитации.
final class WeatherViewModel: ObservableObject {
@Published var temperatureText = ""
private let service: WeatherService
init(service: WeatherService) {
self.service = service
}
}Внедрение зависимостей
Скройте конкретные зависимости за протоколом. ViewModel зависит от абстракции, поэтому тесты могут внедрить mock.
protocol WeatherService {
func fetchTemperature() async throws -> Double
}Создание mock-объекта
mock соответствует протоколу и возвращает заранее подготовленные данные. Он позволяет точно контролировать, что видит ViewModel.
final class MockWeatherService: WeatherService {
var stubbedTemperature: Double = 20
var didCallFetch = false
func fetchTemperature() async throws -> Double {
didCallFetch = true
return stubbedTemperature
}
}Базовый модульный тест
После внедрения mock-объекта Вы проверяете, правильно ли ViewModel преобразует данные.
func testFormatsTemperature() async {
let mock = MockWeatherService()
mock.stubbedTemperature = 25
let vm = WeatherViewModel(service: mock)
await vm.load()
XCTAssertEqual(vm.temperatureText, "25 C")
}Тестирование переходов состояний
ViewModel часто предоставляет перечисление состояний. Протестируйте каждую ветвь, передавая входные данные, которые приводят к ней.
func testLoadingThenLoaded() async {
let vm = FeedViewModel(service: MockFeedService())
XCTAssertEqual(vm.state, .loading)
await vm.load()
XCTAssertEqual(vm.state, .loaded(["A", "B"]))
}Тестирование сценариев ошибок
Заставьте mock выбросить ошибку, чтобы проверить, корректно ли ViewModel обрабатывает сбои и предоставляет состояние ошибки.
final class FailingService: WeatherService {
func fetchTemperature() async throws -> Double {
throw URLError(.notConnectedToInternet)
}
}
func testShowsErrorOnFailure() async {
let vm = WeatherViewModel(service: FailingService())
await vm.load()
XCTAssertEqual(vm.state, .error)
}Проверка взаимодействий
Иногда важно проверить, что зависимость была вызвана, а не только проверить результат. Флаги-шпионы в mock-объекте позволяют проверять поведение.
func testFetchIsCalled() async {
let mock = MockWeatherService()
let vm = WeatherViewModel(service: mock)
await vm.load()
XCTAssertTrue(mock.didCallFetch)
}Тестирование вывода @Published
Вы можете подписаться на свойство @Published с помощью Combine, чтобы собирать отправленные значения и проверять последовательность.
var received: [String] = []
let cancellable = vm.$temperatureText.sink { received.append($0) }
await vm.load()
XCTAssertEqual(received.last, "25 C")
cancellable.cancel()Как сохранять быстроту тестов
Поскольку mock-объекты возвращают данные мгновенно и настоящая сеть не используется, тесты ViewModel выполняются за миллисекунды. Избегайте настоящих таймеров и URLSession — внедряйте имитации также для часов и планировщиков.
Рекомендации
Эффективные тесты ViewModel:
- Внедряйте все зависимости через протоколы
- Проверяйте одно поведение в каждом методе теста
- Покрывайте сценарии успеха, пустого результата и ошибки
- Проверяйте опубликованные результаты, которые считывало бы представление
Быстрая проверка
Проверьте свои знания о тестировании ViewModel.
Итоги
Вы научились изолированно тестировать ViewModel:
- Внедрять зависимости за протоколами
- Использовать mock-объекты для управления входными данными и отслеживания вызовов
- Покрывать состояния успеха, ошибки и пустого результата
- Проверять результаты
@Publishedи переходы состояний
Возможность тестирования ViewModel — результат разделения ответственности в MVVM.
Изучай 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 — локальная установка не требуется.
Все уроки этого курса
- Шаблон MVVM
- Связывание моделей представления с представлениями
- Шаблон координатора
- Тестирование моделей представления