Нужно: интерфейсы файловой системы и реализация в .NET.

Возможный дубликат:
Как вы издеваетесь над файловой системой в С# для модульного тестирования?

Я пишу модульные тесты для своего кода, используя Moq как фальшивую фреймворк.
Мой код включает вызовы в файловую систему, используя прямые вызовы классов System.IO. Например, File.Exists(...) и т.д.
Я бы хотел, чтобы этот код был более подвержен тестированию, поэтому я должен иметь интерфейс, например IFile, с соответствующим методом, например Exists(string path).
Я знаю, что могу написать это с нуля, но я подумал, что, возможно, есть полная, надежная структура, которая имеет как интерфейсы, так и реализации для файловой системы. Эта (желаемая) структура также может быть своего рода "службой", поэтому ее API не обязательно должен быть "эквивалентом интерфейса" для пространства имен System.IO.
Обратите внимание, что мне бы очень хотелось иметь интерфейсы (и не статические методы), чтобы мой код был готов к инъекции зависимостей

Что я получил до сих пор:

  • Как-то похоже, но не тот же вопрос был задан в stackoverflow
  • В codeplex.com существует проект с именем CodePlex Source Control Client (ссылка), которая имеет такие классы в исходном коде (см. /Source/TfsLibrary/Utility/ в исходном коде для конкретных деталей)

Любые другие рекомендации?

Ответ 1

Я написал адаптеры для статических методов System.IO.File и Directory. Затем в моих классах я делаю следующее:

public class MyService {
  public IFile File {private get;set;}
  public MyService() {
    File = new FileImpl();
  }
  public void DoSomething() {
    File.ReadAllText("somefile");
  }
}

Затем вы можете вводить макет в качестве теста для тестирования.

Ответ 2

Хорошо, у меня нет библиотеки файловой системы-макета, которую вы хотите (хотя она может быть где-то там и будет классной), но это может помочь. Одним из интересных понятий, которые возникла у "бихевиористской" школы модульного тестирования, является идея "исходящего интерфейса". В некоторых случаях, как представляется, существует такая же ценность при принятии вызовов, которые объект делает для всей вселенной вещей вне себя, и превращения их в интерфейс, поскольку в типичном акте создания интерфейса для методов внешние мир может называть на ваш объект).

В этом случае вы можете рассмотреть вместо того, чтобы издеваться над всей файловой системой, создавая один или несколько логически последовательных интерфейсов для ответов и услуг, которые нужны вашему объекту из внешнего мира. Вызовы просто отвечали на вопросы, на которые вы ответили... не диктуют реализацию. Затем вы можете использовать инъекцию зависимостей, как вы упомянули, для внедрения в реализацию, которую вы хотите для своих тестов. И вы, вероятно, будете использовать Moq для этого, так как вы знакомы с ним.

Итак, ваш "исходящий интерфейс" может иметь метод, называемый DoFileExist(). Он может принять путь. Или, если есть бизнес-вопрос "более высокого уровня", на который пытается ответить ваш объект, и если посмотреть, существует ли файл, это просто способ, на который задан ответ, тогда ваш исходящий интерфейс может не иметь метода о существовании файла вообще. Это может быть нечто вроде "DoIAppearToHaveAccessToTheFileServer" или даже "IsThereAPreviouslySavedGame".

Это некоторая работа, но она может быть верна принципам хорошего модульного тестирования... пусть ваш объект-под-тест выражает то, что он пытается сделать, и пусть ваши юнит-тесты проверяют его и только он. Просто мысль... надеюсь, что это поможет.

Ответ 3

Я поддерживаю проект Jolt.NET на CodePlex, который содержит библиотеку для создания таких интерфейсов и их реализации для вас. Подробнее читайте в Jolt.Testing.

Ответ 4

http://systemwrapper.codeplex.com/ предлагает хороший выбор, хотя я еще не пробовал его. Похоже, автор может использовать некоторую помощь при завершении проекта.

Ответ 5

Я понимаю, что пакет Typemock может делать такие вещи.

Ответ 6

Вместо того, чтобы издеваться над файловым интерфейсом, я бы традиционно решил издеваться над самой файловой системой. Это относительно простая задача для любой серьезной ОС. Вы можете легко создать файловую систему userpace с помощью Mono.Fuse, реализация С# FUSE, файловые системы в USErspace. Я не уверен, что если какой-либо перенос потребуется для Dokan, FUSE для Windows, но FUSE отлично работает в Linux, OSX, и Solaris.