Мой совет состоит в том, чтобы немного перестроить ваш класс Configuration
. Поскольку ваш вопрос носит теоретический характер, с небольшим практическим аспектом (сбой модульного теста), я предоставлю некоторую ссылку для резервного копирования моих идей.
Прежде всего, введите Configuration
нестатический класс. У Miško Hevery, инженера в google, есть очень хорошая речь о OO Design for Testability, где он специально затрагивает глобальное состояние как плохой выбор дизайна, особенно если вы хотите его протестировать.
Ваша конфигурация может принимать пример с помощью конструктора RegistryProvider
(предположим, вы слышали о принципах впрыскивания зависимостей). RegistryProvider
Ответственность будет просто считывать значения из реестра, и это единственное, что нужно делать. Теперь, когда вы проверите Configuration
, вы предоставите RegistryProvider stub
(если вы не знаете, какие заглушки и макеты - google it, они просты по своей природе), где вы будете указывать значения для конкретных записей в реестре.
Теперь преимущества:
- вас есть хорошие
unit tests
, потому что вы не полагаться на реестр
- не имеют глобального состояния (Тестируемость)
- тесты не зависят друг с другом (каждый из них имеет отдельный экземпляр
Configuration
)
- ваши тесты не зависят от среды, в которой они выполняются (у вас могут не быть прав доступа к реестру, но вы можете проверить свой
Configuration
класса)
Если вы чувствуете, что вы не совсем хорошо Dependency Injection, я рекомендовал бы изумительное произведение искусства и технику, при условии, смертной душу гением Марка Seemann, называется Dependency Injection in .NET. Одна из лучших книг, которые я прочитал о дизайне классов, который ориентирован на разработчиков .NET.
Для того, чтобы мой ответ более конкретен:
Должен ли я использовать отражение заново построить класс для каждого теста?
Нет, вы никогда не должны использовать рефлексию в своих тестах (только если это не другой случай). Рефлексия сделает вас тестами:
- хрупкой
- трудно понять
- трудно поддерживать
Используйте объектно-ориентированные практики с конъюнкцией инкапсуляции для достижения скрытия реализации. Затем проверяйте только внешнее поведение и не полагайтесь на внутренние детали реализации. Это будет зависеть только от внешнего поведения, а не от внутренней реализации, что может сильно измениться.
Следует ли перепроектировать этот класс, чтобы проверить реестр в свойстве , а не на конструкторе?
Проектирование класса, как описано в моем ответе, позволит вам протестировать ваш класс, не получающий доступ к реестру вообще. Это краеугольный камень модульных тестов - не полагаться на внешние системы (базы данных, файловые системы, web, реестр и т. Д.). Если вы хотите протестировать, если может получить доступ к реестру вообще - напишите отдельные интеграционные тесты, где вы будете записывать в реестр и читать с него.
Теперь у меня недостаточно информации, чтобы сообщить вам, следует ли читать реестр через RegistryProvider
в конструкторе Configuration
или лениво читать реестр по требованию, это сложный вопрос. Но я определенно могу сказать - старайтесь избегать глобального состояния как можно больше, старайтесь минимизировать зависимость от деталей реализации в тестах (это относится к принципам OO в целом) и пытайтесь тестировать объекты отдельно, т. Е. Без доступа к внешним системы. Тогда вы можете имитировать исключительные случаи, например, вы придерживаетесь класса, как ожидалось, когда реестр недоступен? Это очень сложно воссоздать такой сценарий, если вы напрямую обращаетесь к реестру через статические члены класса Configuration
.
Вы можете переместить код загрузки в метод класса Configuration вместо конструктора. Затем вы можете выполнить тестирование функции с помощью разных сценариев. – rgunawan
@rgunawan Согласитесь, это похоже на действительно простую модификацию. Просто переместите все тело конструктора в метод и позвольте конструктору просто вызвать этот метод. Тогда один и тот же метод можно было бы вызывать из модульных тестов. Кажется простым. –