Проблема с NUnit при определении каталога сборки
Я только начал работать с NUnit, чтобы обеспечить тестовое покрытие для моих проектов.
В моей основной library.dll мне нужно загрузить данные конфигурации из внешнего файла, который идет вместе с библиотекой library.xml.
Это прекрасно работает, когда я использую библиотеку, потому что я использую следующее, чтобы получить каталог, в котором нужно искать файл конфигурации:
string settingspath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Проблема, которую я заметил, заключается в том, что, когда я выполняю модульное тестирование с помощью NUnit, он копирует мои сборки в теневую копию, но не берет с собой другие файлы, поэтому, конечно, моя инициализация завершается неудачно из-за отсутствия файлов конфигурации,
Должен ли я делать что-то другое, чтобы найти файлы конфигурации из моей библиотеки? (это серверное приложение, и я не хочу использовать стандартные настройки приложения или локальные настройки пользователя и т. д.)
7 ответов
При модульном тестировании, как правило, рекомендуется избегать внешних зависимостей, таких как файловая система и базы данных, путем насмешки / заглушения вызывающих их подпрограмм - таким образом ваши тесты будут более локализованными, менее хрупкими и быстрее. Посмотрите, можете ли вы удалить зависимости, предоставив ложную информацию о конфигурации.
Использование можно использовать TestContext.CurrentContext.TestDirectory
как упоминал Чарли Пул из NUnit здесь:
Необходимость доступа к файлам в том же каталоге, что и у тестовой сборки, является наиболее часто упоминаемой причиной отключения теневого копирования. Тем не менее, это ложно.
NUnit не копирует никакие сборки: теневое копирование является функцией самого.NET. Следовательно, проблема должна рассматриваться как "Как я могу получить доступ к файлу, где он находится?" а не "Как я могу скопировать файл туда, где я думаю, что это должно быть?"
Есть три способа найти файл, который находится в том же каталоге, что и сборка:
1) Используйте Assembly.Codebase - это даст вам местоположение в качестве URI, которое вы должны затем преобразовать в соответствующий путь.
2) Используйте текущий каталог, который NUnit исторически установил в каталог, содержащий исполняющуюся тестовую сборку. Тем не менее, это может быть не так для будущих выпусков.
3) Используйте TestContext.CurrentContext.TestDirectory от NUnit, который доступен в самых последних выпусках.
Все эти подходы на самом деле используют Assembly.Codebase под прикрытием, а NUnit корректно преобразовывает URI в #2 и #3. Обычный подход к использованию Assembly.Location неверен, если только вы на самом деле не хотите определить местоположение кэша теневой копии.
Для использования справочных файлов в моих модульных тестах я использую Assembly.Codebase, которая работает, даже если включено теневое копирование. Возможно, вы захотите попробовать...
Он возвращает строку в формате Uri.. поэтому вам нужно создать экземпляр Uri из строки кодовой базы и использовать Uri.LocalPath, чтобы получить фактический путь к папке.
Однако для производственного кода BaseFolder должен быть извлечен из хорошо известного места (например, ключ реестра, установленный через установщик в Windows). Все поиски файлов должны быть укоренены из этого baseFolder.
Даже если теневое копирование активно, AppDomain.CurrentDomain.BaseDirectory
указывает на исходное местоположение тестовых DLL.
Однако, если вы можете встроить свои тестовые данные в виде ресурсов в свою DLL, это будет намного безопаснее, поскольку нет никаких дополнительных файлов, которые могут быть потеряны.
Вы можете отключить теневое копирование в командной строке, используя /noshadow
переключатель. Параметры командной строки описаны здесь
Установлен ли внешний файл как часть сборки вашего dll? Если вы включите его в проект и установите его всегда копировать в "Копировать в вывод" в свойствах файла, то он должен перейти в теневую директорию, я думаю.
Это может помочь вам.
Мы включаем тестовый ресурс в тестовый проект (в данном случае в папку "TestData").
В Visual Studio для доступа к ресурсу в тестовой отметке
Когда сборка проекта оставляет изображение в папке 'bin\Debug'
и ты пишешь путь
string fullImagePath = @".\TestData\vcredist.bmp";
Как вы отметили, Assembly.Location
возвращает бесполезный временный путь где-то в ShadowCopyCache NUnit, и это необходимо, чтобы избежать блокировки файла и предотвращения перекомпиляции.
У меня были дополнительные проблемы: во-первых, средство запуска графического интерфейса NUnit 2 не работает так же, как средство запуска графического интерфейса пользователя NUnit 3 (теперь оно называется TestCentric). Во-вторых, мне иногда нужно вызвать тестовые методы из другого исполняемого файла. Для справки, вот пути, которые я получаю:
NUnit 2:
AppDomain.CurrentDomain.BaseDirectory = @"C:\PathToNUnitProject\"
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = @"C:\PathToNUnitProject"
NUnit.Framework.TestContext.CurrentContext.TestDirectory = @"C:\PathToNUnitProject\bin\Debug"
NUnit 3:
AppDomain.CurrentDomain.BaseDirectory = @"C:\PathToNUnitProject\bin\Debug\"
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = @"C:\TestCentric\testcentric-gui-1.2.0"
NUnit.Framework.TestContext.CurrentContext.TestDirectory = @"C:\PathToNUnitProject\bin\Debug"
Когда тестовый метод вызывается извне NUnit:
AppDomain.CurrentDomain.BaseDirectory = something else entirely
NUnit.Framework.TestContext.CurrentContext.WorkDirectory = Exception
NUnit.Framework.TestContext.CurrentContext.TestDirectory = Exception
Для меня решение: использовать NUnit.Framework.TestContext.CurrentContext.TestDirectory
, как в ответе Джеффа, в пределах попытки. Если это не сработает, возвращаемый путь будет одинаковым для обеих версий NUnit.
Столкнулся с той же проблемой... вот моя тренировка:
Перед запуском SUT обновите базовый каталог AppDomain следующим образом...
String root_path = "{{your path}}";
AppDomain.CurrentDomain.SetData("APPBASE", root_path);