Но потом я отверг эту идею, потому что она
не очень поможет. Я мог бы проверить
объект SieveClient легче,
правда. Но тогда у меня было бы то же самое
проблемы с тестированием нового объекта.
Мне кажется, что это просто
до проблемы на потом. Особенно
так как у меня ничего нет, я мог бы повторно использовать
новый класс для.
Это не будет той же проблемой.
Я предполагаю, что вам нужен SieveClient для управления созданием других объектов внутри, потому что это часть API, которую вы не хотите предоставлять. Если по этой причине, разделяя их, у вас больше нет той же потребности, поскольку у вас может быть SieveClient, контролирующий привязки, а другая часть , которая выполняет протокол , получает экземпляры, которые будут работать с .
Выполнив вышеизложенное, вы можете передать макетированные объекты вашей реализации протокола . Тогда у этих издевательств будут любые ожидания, которые могут вам понадобиться . Если вы обнаружите, что в конечном итоге он слишком вовлечен, то вам, вероятно, нужно переориентировать обязанности, что в любом случае обычно приводит к более чистой / более простой реализации протокола (если вы обнаружите, что вам нужно выполнять эти модульные тесты).
Выше говорилось, что вам также нужно подумать, не является ли код, который вы пытаетесь протестировать, максимально сфокусированным на протоколе и не имеет каких-либо дополнительных элементов. Если это так, то он не будет хорошим кандидатом для модульного тестирования, поскольку его единственная ответственность - взаимодействие с внешней системой. Я бы решил, насколько важна спецификация протокола в этой системе, и если бы все было связано с интеграцией с внешней системой, я бы отнесся к ней как к целенаправленному интеграционному тесту, который вместо этого затрагивает реальную внешнюю систему и отделен от модульных тестов (таким образом, это не влияет на скорость, необходимую для запуска модульных тестов остальной системы).
Перечитав вопрос из-за редактирования, я должен подчеркнуть то, что я сказал о целевых интеграционных тестах выше. Вы спрашиваете:
Но поскольку CocoaAsyncSocket предоставляет
много разных методов для чтения данных
из розетки я должен точно знать
которые используются протоколом
объект в каком порядке. Я не хочу, чтобы мой
модульный тест, который будет зависеть от
детали реализации моего протокола
объект. Так что мне здесь делать?
Реализация фиктивного объекта для сокета
класс от руки? Это кажется нетривиальным,
поэтому мне, вероятно, понадобятся юнит-тесты для
это тоже. Это хорошая идея?
Если вы имеете дело с очень сложным объектом, и весь этот объект связан с интеграцией за пределы, вам лучше всего избегать его в рамках модульных тестов. В этом сценарии вы хотите сфокусированный интеграционный тест / поразить реальную внешнюю систему. Это не означает, что все модульные тесты остального кода, попадания во внешнюю систему, просто очень простая единица кода / класса, которая использует этот объект .
Вполне возможно, что в вашем сценарии такой объект является SieveClient, в этом случае забудьте о модульных тестах этого фрагмента кода. Вместо этого вы хотите смоделировать SieveClient при тестировании кода, который его использует. С другой стороны, если вы обнаружите, что SieveClient намного больше, вы захотите добавить класс, который упрощает эти аспекты взаимодействия, и это было бы тем, что вы высмеиваете при тестировании SieveClient, а также тем, на что вы делаете целенаправленный интеграционный тест.
Этот тип тестов - очень эффективный способ убедиться, что код, взаимодействующий с внешним устройством, работает должным образом, так как это находится в центре внимания как класса, так и тестов. В случае, если что-то во внешней системе начинает работать по-другому, вы четко это замечаете - в отличие от того, что это смешалось с логикой вашего приложения или, в худшем случае, вообще не тестировалось.