Подтвердить что ты не робот

Тестирование модуля С#: тестирование метода, использующего MapPath

Прежде всего, я знаю, что этот вопрос опасно близок к: Как MapPath в unit test на С#

Я надеюсь, что у него другое решение. Мой вопрос:

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

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

Строка ошибок (в моем коде проверки NOT my unit test):

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

Упрощенный: unit test вызывает метод в моей программе, который вызывает Server.MapPath, который затем не работает.

4b9b3361

Ответ 1

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

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());

Ответ 2

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

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

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

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

Ответ 3

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

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

Здесь я спросил:

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

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

Ответ 4

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

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() обрабатывает отсутствующий файл.