Подтвердить что ты не робот

Включая файл ресурсов для Unit test в проекте С#

У меня есть некоторые функции, которые читают и изменяют файлы. Чтобы сделать модульные тесты независимыми от любых проблем файловой системы, я хочу включить файлы внутри проекта.

Однако, моя функция должна получать файлпат, и все, что я могу получить от сборки, - это FileStream. Любая идея, как я могу получить путь к файлу ресурса в проекте?

System.Reflection.Assembly a = System.Reflection.Assembly.Load(assemblyName);
FileStream stream = a.GetFile(assemblyName + "." + fileName);

Спасибо!

4b9b3361

Ответ 1

Мое обычное решение этой проблемы заключается в том, что я реорганизую свою программу, чтобы открыть файл в вызывающем методе, а затем передать Stream вместо передачи имени файла и открытия там файла.

Для тестирования это позволяет мне передавать MemoryStream, поэтому я могу написать свой unit test без использования файловой системы вообще. Иногда даже проще проверить правильность написания данных и ускорить его, особенно для большего количества тестов. Вам просто нужно помнить, чтобы очистить MemoryStream после написания, поскольку .NET не всегда делает это автоматически.

Пример из одной из моих программ:

public TestSaveAndLoad()
{
  [... create data to save ...]
  using (MemoryStream targetStream = new MemoryStream())
  {
    target.Save(targetStream);
    targetStream.Flush();
    targetStream.Seek(0, ...);
    target.Load(targetStream);
  }
  [... assert that the loaded data equals the saved data ...]
}

Ответ 2

Встроенный ресурс не существует в файловой системе, поэтому он не имеет никакого пути к файлу.

У вас есть два варианта:

  • Измените API своего SUT, чтобы он принимал Stream, а не только путь к файлу. Это решение гораздо предпочтительнее.
  • Сохраните внедренный ресурс во временный файл во время модульного тестирования, убедившись, что он удалит его снова после каждого тестового примера.

Первое решение - отличный пример того, как TDD ведет нас к лучшим, более гибким API.

Ответ 3

Вы можете установить файлы данных для копирования в каталог bin при создании проекта, а затем ссылаться на них через Directory.GetCurrentDirectory() в вашем тесте. Или даже оставить их там, где они есть, и просто использовать относительный путь на основе текущего каталога.

Лучше, однако, было бы реструктурировать ваш код, чтобы полагаться на класс Stream, а затем использовать комбинацию издевательств и инъекций зависимостей, чтобы снабжать макетный поток данными - или использовать поток памяти, если фальсификация работает лучше.

Ответ 4

Если вы установите действие по сборке файлов для копирования, вы можете предсказать, где должен быть файл (вероятно, связка.. \.. \.. \, но все же). Я предполагаю, что у вас есть вход для вашего метода для имени файла, поэтому он должен работать нормально.

Как предложение, можно ли абстрагировать фактическое чтение/изменение этого файла в метод и передать строковое значение? Единственная причина, почему я это понимаю, это то, что он пахнет интеграционным тестом (касаясь файловой системы).