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

HttpContextWrapper все, что.... полезно?

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

По причинам, не связанным с этим разговором, когда дело касалось использования HttpContext, мы решили использовать недавно созданный класс HttpContextWrapper, а не изобретать что-то самодельное. Одна вещь, которую мы представили, - это возможность обмена в HttpContextWrapper (например, для модульного тестирования). Это было полностью вдохновлено тем, как Oren Eini обрабатывает модульное тестирование с помощью DateTimes (см. Статью, образец, который мы также используем)

public static class FooHttpContext
{
    public static Func<HttpContextWrapper> Current = () 
         => new HttpContextWrapper(HttpContext.Current);

    public static void Reset()
    {
        Current = () => new HttpContextWrapper(HttpContext.Current);
    }
}

Ничего особенного. И это прекрасно работает в нашем коде контроллера. Кикер пришел, когда мы пошли писать блок-тесты. Мы используем Moq как нашу насмешливую структуру, но, увы,

var context = new Mock<HttpContextWrapper>() 

ломается, поскольку HttpContextWrapper не имеет без параметров ctor. И что это такое, как параметр ctor? Объект HttpContext. Поэтому я попал в ловушку.

Я использую предписанный способ развязки HttpContext - но я не могу высмеять значение, потому что исходный объект HttpContext был запечатан и поэтому трудно проверить. Я могу отобразить HttpContextBase, из которых оба получаются, но это на самом деле не дает мне то, что мне нужно. Я просто пропустил точку где-то в отношении HttpContextWrapper?

Изменить, чтобы прояснить намерение

Мы нашли способы решить проблему - но я думаю, что конечный вопрос, который мы уходим, - это то, что значение HttpContextWrapper приводит к таблице? Я не сомневаюсь, что у кого-то был а-ха! момент с ним, но он просто не приходит ко мне. Большинство сообщений, которые я вижу здесь, обсуждают с точки зрения тестируемости, но мой собственный опыт заставил меня поверить, что в этом контексте это не принесло многого. Если мы не сделаем это неправильно. (Вполне возможно).

4b9b3361

Ответ 1

Вы должны использовать абстрактный HttpContextBase, который намного проще высмеивать вместо HttpContextWrapper.

public static Func<HttpContextBase> Current = 
    () => new HttpContextWrapper(HttpContext.Current);

И в unit test:

SomeClass.Current = MockHttpContextBase(); // Sorry I don't know the syntax for Moq

Ответ 2

Это сообщение в блоге объясняет это довольно хорошо:

http://splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext

Дело в том, что "vintage" HttpContext не реализует HttpContextBase и не является виртуальным, и поэтому не может быть посмешен. HttpContextBase был введен в 3.5 как макет альтернативы. Но есть еще проблема, что vintage HttpContext не реализует HttpContextBase.

Таким образом, HttpContextWrapper - это удобный класс-оболочка (или "kludge" ), который реализует HttpContextBase, и может использоваться при инъекции "реального" HttpContext с использованием IOC, обычно с помощью метода factory, как это: () => new HttpContextWrapper(HttpContext.Current)