В настоящее время читает "Искусство модульного тестирования" Роя Ошерова. Я на полпути к этому, и пока это потрясающая книга. Я собираюсь попросить всех оставить из этого обсуждения контейнеры IOC . Он лишь кратко упоминает о них (фактически заявляет, что МОК выходит за рамки книги, которую я не понимаю, и является одним из немногих мест, где я могу критиковать книгу). В любом случае, за исключением МОК, существуют различные методы:
- Конструктор Инъекция
- Ввод имущества
- Программные фабрики и статика
- Программные фабрики и виртуальные методы
- Метод инъекции
- Элемент списка
Хорошо, я опишу, что мне не нравится в каждом методе выше.
1. Внедрение в конструктор - делает инициализацию объекта запутанной и более сложной, особенно если вам нужно передать много зависимостей.
2. Property Injection - Рою, похоже, нравится эта техника, но она мне менее всего нравится. Если у вас есть куча зависимостей, то пользователь должен не забывать инициализировать каждую и каждую зависимость, которая требуется для класса. Я бы сказал, что это подвержено ошибкам и грязно. Очень затрудняет инициализацию класса для тех, кто не знаком с ним.
3. Программные фабрики и статика - Хотя я не думаю, что это плохая техника, мне не нравится полагаться на состояние. Мне нравится иметь дело с полностью лишенным состояния объектом, но пока я считаю, что это лучшая техника.
4. Программные фабрики и виртуальные методы - Подобно вышеописанным методам, но позволяет вам наследовать от класса и переопределять только функцию, которая устанавливает вашу зависимость, и заменяет ее на заглушки. Мои мысли похожи на 3 - это просто немного запутывает человека, пытающегося выяснить, почему не прошел модульный тест.
5. Внедрение метода - Все, что я могу сказать, это ewwwwwww ... передать каждую и каждую зависимость для каждого метода, который вы вызываете. Достаточно сказано.
Я подумал о другом способе, который я предпочитаю всем перечисленным выше методам. Я обычно не поощряю условную компиляцию, но думаю, что в некоторых местах, где вы используете ее слегка, это может иметь смысл. Я предлагаю стандартизировать имя для метода, который устанавливает ваши зависимости для вашего тестирования. Например:
.InitalizeDepForTesting(IFileSystem file, IDatabase data, IEventLog event, ...)
Затем оберните вышеприведенный оператор в оператор условной компиляции:
#If DEBUG
public void InitializeDepForTesting(...)
#endIf
Таким образом, ваши внутренние зависимости продолжают работать как есть и не требуют изменений. Вы также предотвращаете испортить конструктор и передать все свои зависимости с кучей других «вещей». Ничего не меняется в том, что касается вашего производственного кода, и очень легко сразу увидеть, как вы должны инициализировать объект для тестирования. Что вы все думаете?