Как создать тестируемый код с использованием классов .Net IO? - PullRequest
7 голосов
/ 07 января 2012

Я хочу создать проверяемый модулем код, который макетирует вызовы к классам .Net System.IO, так что я действительно могу выполнять модульное тестирование вместо зависимости от файловой системы. Я использую классы SystemWrapper , чтобы обернуть вокруг классов BCL.

Я пытаюсь получить простой пример работы, чтобы увидеть, существует ли файл.

Проблема, с которой я столкнулся, заключается в том, что внедрение зависимости в классе не работает, поскольку создание экземпляра зависимости (через StructureMap ) требует знания передаваемого параметра конструктора, который при этом не будет доступен время, также нет конструктора по умолчанию.

пример кода:

// don't want to create dependency here like so
//IFileInfoWrap fileInfoWrap = new FileInfoWrap(filename);

// using service locator (anti-pattern?!) since it can't be 
// injected in this class
var fileInfoWrap = ObjectFactory.GetInstance<IFileInfoWrap>(
    new ExplicitArguments(new Dictionary<string, object>
    {
        {"fileName", filename}
    }));

Console.WriteLine("File exists? {0}",  fileInfoWrap.Exists); 

Что мне не нравится, так это то, что зависимость не внедряется, ObjectFactory не должен быть здесь (но я не вижу другого способа создать это). ExplicitArguments делает его беспорядочным, а аргумент name является волшебной строкой.

Для того, чтобы заставить это работать, класс конфигурации StructureMap должен знать, какой конструктор я хочу использовать (я только начал с StructureMap, так что это может быть неправильный способ его настройки):

ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
    {
        scan.AssembliesFromPath(".");
        scan.RegisterConcreteTypesAgainstTheFirstInterface();
        scan.WithDefaultConventions();
    });

    // use the correct constructor (string instead of FileInfo)
    x.SelectConstructor(() => new FileInfoWrap(null as string));

    // setting the value of the constructor
    x.For<IFileInfoWrap>()
        .Use<FileInfoWrap>()
        .Ctor<string>("fileName")
        .Is(@".");
});

Кто-нибудь нашел лучшее решение для создания тестируемого кода для классов System.IO? Я знаю, что часть проблемы заключается в разработке классов System.IO.

1 Ответ

5 голосов
/ 07 января 2012

Подход, который я использовал очень успешно, состоит в том, чтобы прокрутить мои собственные типы прокси для типов, найденных в System.IO и других частях FCL. Например. Я хочу взять зависимость от System.IO.File. Я создаю библиотеку с именем System.IO.Proxies и добавляю конкретный тип File и интерфейс IFile. Интерфейс IFile предоставляет члены, эквивалентные всем тем, которые мне требуются от System.IO.File, и конкретный тип реализует эти члены, не делая ничего, кроме переадресации вызовов методов на System.IO.File. System.IO.Proxies исключено из модульного тестирования и покрытия кода. В моей потребительской сборке я беру зависимость только от System.IO.Proxies и, в частности, я беру зависимость только от IFile. Таким образом, я могу легко смоделировать эту зависимость и достичь 100% покрытия кода для моей потребляющей сборки.

(Обратите внимание, что это адаптированная версия моего более общего ответа на предыдущий вопрос.)

...