IOS VIPER: Как протокол помогает в модульном тестировании?
Меня немного смущает преимущество протоколов в архитектуре VIPER. Я понимаю, что DI (Dependency Injection) достигается с помощью протоколов и помогает избежать прямой зависимости между объектами - согласен.
Но я смотрю на реальную выгоду с точки зрения использования, примером может быть - особенно то, как протоколы помогают извлечь выгоду в модульном тестировании (тестирование части Interactor).
Разве мы не можем достичь того же с помощью метода Callback, используя блоки? Надеюсь, что кто-то может помочь мне понять с точки зрения использования с некоторым примером
ура
2 ответа
Использование обратного вызова, например, от Interactor к Presenter, может усложнить тестирование Presenter.
При написании тестов для того, как Presenter обрабатывает ввод (отправленный из Interactor), ваш тест должен будет вызвать некоторый метод Presenter, который заставит Presenter вызвать Interactor, что приведет к тому, что Interactor отправит данные Presenter.,
Если Presenter реализует протокол, определенный Interactor, ваш тест может просто напрямую вызвать соответствующий метод ввода на Presenter.
Что касается объявления протоколов, я практикую TDD в стиле фиктивных ролей, а не объектов ( http://www.jmock.org/oopsla2004.pdf). Протоколы помогают обеспечить лучшую абстракцию, сосредотачиваясь на том, что делает объект (его роль), а не на том, как он это делает.
Протоколы сами по себе не представляют особой ценности для модульных тестов. Ваши модульные тесты обеспечат двойные тесты ( http://martinfowler.com/bliki/TestDouble.html) для зависимостей тестируемой системы. Даже если вы представляете зависимости как конкретные классы, вы все равно можете создавать тестовые двойники для своего теста.
В Objective-C вы можете использовать фиктивную библиотеку, такую как OCMock ( http://ocmock.org/) или OCMockito ( https://github.com/jonreid/OCMockito), для создания заглушек, шпионов или издевательств конкретный класс.
В Swift вы можете создать свои тестовые двойники, создав подклассы каждого из конкретных классов, используемых в качестве зависимостей.
Короче говоря, протоколы используются не для облегчения модульного тестирования, а для описания на более высоком уровне абстракции, что делает приложение.
Вот пример того, как абстрактные протоколы были полезны после факта:
Я создал протокол для представления действий, которые пользователь может выполнять на экране, например ProfileUserActions
, которые имели такие действия, как changeName
, а также changeAddress
, Ведущий реализован ProfileUserActions
и вид принял ProfileUserActions
как зависимость. Когда пользователь нажимает кнопку на экране, представление отправляет соответствующее сообщение userActions
объект.
Когда я захотел добавить аналитику, я смог создать новый, независимый ProfileAnalytics
класс, который также реализован ProfileUserActions
, Я вставил объект аналитики между View и Presenter, что позволило приложению захватывать аналитику, не изменяя View или Presenter.
Используя протокол, вам легче поменять реализацию в вашей структуре VIPER. Например, у вас может быть интерактор, который работает с классом, который пишет в файловую систему. Вы не хотите тестировать файловую систему в своих модульных тестах, поэтому вместо этого, если вы поместите операции записи файловой системы в свой интерактор за протоколом, вы можете заменить операции записи файловой системы реализацией в памяти.
Что касается протокола на самом интеракторе, я думаю, что он будет более прагматичным в вашем выборе. Если ваш тестер легко построить для теста и он не вызывает никаких побочных эффектов как часть тестирования, то, вероятно, нет необходимости в протоколе. С другой стороны, если вам нужно создать ряд других зависимостей, то может быть полезно, чтобы интерактор соответствовал протоколу, чтобы вам было легче подделать выходные данные, которые вы получаете от интерактора.