Модульное тестирование в C #: тестирование метода, использующего MapPath - PullRequest
19 голосов
/ 11 августа 2009

Прежде всего, я знаю, что этот вопрос опасно близок к: Как MapPath в модульном тесте в C #

Я надеюсь, однако, что у него есть другое решение. Моя проблема следует:

В моем коде у меня есть объект, который нужно проверить. Я создаю модульные тесты для каждого метода проверки, чтобы убедиться в его правильности. Я создаю фиктивные данные и загружаю их в объект, затем проверяю их. Проблема заключается в том, что в процессе проверки при возникновении ошибки присваивается код ошибки. Этот код ошибки используется для сбора информации об ошибке из XML-файла с помощью Server.MapPath. Однако при попытке получить файл XML возникает исключение, означающее, что файл не найден.

Поскольку MapPath находится в моем коде проверки, а не в модульном тесте, как мне заставить мой модульный тест распознавать путь? Имеет ли этот вопрос смысл?

Строка ошибки (в моем коде проверки НЕ мой модульный тест):

XDocument xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml"));

Упрощено: модульный тест вызывает в моей программе метод, который вызывает Server.MapPath, который затем завершается ошибкой.

Ответы [ 4 ]

15 голосов
/ 11 августа 2009

Я бы абстрагировал «провайдера файловых имен» в класс, который просто возвращает местоположение, тогда вы можете сделать это намного проще.

public class PathProvider
{
    public virtual string GetPath()
    {
        return HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml");
    }
}

Затем вы можете использовать класс PathProvider напрямую ...

PathProvider pathProvider = new PathProvider();
XDocument xdoc = XDocument.Load(pathProvider.GetPath());

Или смоделируйте это в своих тестах:

PathProvider pathProvider = new MockPathProvider(); // using a mocking framework
XDocument xdoc = XDocument.Load(pathProvider.GetPath());
11 голосов
/ 12 августа 2009

После некоторого тщательного поиска в Google и некоторой помощи коллеги мы пришли к простому решению, уже встроенному в .net

Над модульными тестами, которые обращаются к процессу проверки, я добавил:

 [TestMethod()]
 [HostType("ASP.NET")]
 [UrlToTest("http://localhost:###/upload_file.aspx")]
 [AspNetDevelopmentServerHost("Path To Web Application", "Path To Web Root")]

Это работает отлично. По сути, при вызове теста он загружает URL-адрес с указанным модульным тестом при загрузке страницы. Поскольку это веб-сайт, который сейчас вызывает модульный тест, проверка будет иметь доступ к Server.MapPath. Это решение может не работать для всех, но оно идеально подходит для этого. Спасибо за все, что вы внесли.

1 голос
/ 11 августа 2009

Я бы извлек методы, которые принимают ваши зависимости в качестве аргументов:

public void Validate(HttpContext context)
{
    ValidatePath(context.Server.MapPath("App_Data/ErrorCodes.xml"));
}

public void ValidatePath(string path)
{
    XDocument xdoc = XDocument.Load(path);
    ValidateDocument(xdoc);
}

public void ValidateDocument(XDocument xdoc)
{
    // Original code
}

Затем вы можете проверить различные методы независимо друг от друга. Например, тестирование того, как ValidatePath() обрабатывает отсутствующий файл.

1 голос
/ 11 августа 2009

Попробуйте использовать Rhino Mocks или альтернативную структуру для Mock для httpContext (или других зависимых объектов) Или вы можете написать свои собственные фиктивные объекты. Или напишите класс MapPathWrapper, унаследуйте его от класса MapPathWrapperBase для вашей реальной среды, затем в модульных тестах создайте объект MockMapPathWrapper.

Должно быть много примеров насмешек над SO.

Вот один, который я спросил:

Как использовать Rhino Mocks для макетирования HttpContext.Application

UPDATE У меня есть опыт работы только с Asp.Net MVC, с веб-формами, которые я представляю, это будет намного сложнее из-за отсутствия класса HttpContextBase.

...