Нужно: интерфейсы файловой системы и реализация в .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.