Я решил добавить модульные тесты в свой проект и продолжить разработку способом, управляемым тестами. В настоящее время я работаю над реализацией модульных тестов для моего клиентского объекта ManageSieve, и я не уверен, как лучше всего протестировать этого зверя.
Мой объект SieveClient
использует два других объекта для сетевого взаимодействия. : CocoaAsyncSocket
и мой собственный объект SaslConn
, который является моей оболочкой для библиотеки Cyrus SASL для обработки методов аутентификации. Для тестирования мне нужно заменить их на фиктивные объекты. Я собираюсь использовать фреймворк OCMock для этого. Я не совсем уверен, как это сделать, поскольку объект SieveClient должен сам создавать эти объекты. Прямо сейчас я перезаписываю (приватные) сеттеры для этого объекта, чтобы всегда устанавливать мои фиктивные объекты, используя метод OCMocks partalMockForObject:
. Но мне кажется, что это неправильно. Есть идеи, как это можно решить лучше?
Другая часть, с которой у меня проблемы, - это сама розетка. Чтобы иметь возможность проверить детали протокола, мне нужен способ вернуть предопределенные тестовые данные из сокета. Я полагаю, я мог бы просто использовать механизмы OCMock для подделки возвращаемых значений из сокета. Но так как CocoaAsyncSocket
предоставляет много разных методов для чтения данных из сокета, я должен точно знать, какие объекты протокола используются в каком порядке. Я не хочу, чтобы мой модульный тест зависел от деталей реализации моего объекта протокола. Так что мне здесь делать? Реализовать фиктивный объект для класса сокета вручную? Это кажется нетривиальным, поэтому мне, вероятно, понадобятся и модульные тесты для этого. Это хорошая идея?
Я читал, что, если что-то сложно проверить, оно, вероятно, тоже не очень хорошо разработано. Но я не вижу, как я мог бы добиться большего успеха, поскольку сложная часть заключается во взаимодействии с сокетом, который я должен сделать.
Если вы хотите увидеть код, вы можете найти его в Bitbucket: SieveClient .m и SieveClient.h
Итак, я прочитал о Внедрении зависимостей и думаю, что собираюсь использовать это, чтобы получить AsyncSocket
и SaslConn
объектов в мой объект SieveClient
. Я изменю свой конструктор, чтобы принимать эти объекты и использовать их. Поскольку пользователю этого класса обычно нет дела до сокета и объекта SASL, я добавлю фабричный метод (в форме вспомогательного конструктора), который просто создает эти объекты и передает их конструктору.
Но это решает только первую (и более легкую) часть моей проблемы тестирования.