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

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

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

Что я получил так далеко:

  • Как-то похожий, но не тот же вопрос был задан в stackru
  • На http://www.codeplex.com/ есть проект с именем Client Control Source CodePlex ( ссылка), который имеет такие классы в исходном коде (см. /Source/TfsLibrary/Utility/ в исходном коде для уточнения деталей)

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

6 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам