Как правильно смоделировать HttpContextBase, чтобы мои модульные тесты работали

1

Учитывая следующую функцию:

public static void Write(HttpContextBase contextBase, IUnitOfWork unitOfWork, LogLevel level, string title, string message, params AdditionalProperty[] properties)
{
    // Some variables that are set for writing the logs.
    //      - client: When the HttpContext is null, 'N.A.' is used, otherwise the I.P. address of the requesting computer.
    //      - userIdentifier: When the HttpContext exists and a value is stored in the cookie, the value of the cookie, otherwise an empty guid.
    //      - requestIdentifier: When the context is existing and a request have been made on a controller, a unique value identifying this request, otherwise an empty guid.

    string client = (contextBase.ApplicationInstance == null || contextBase.ApplicationInstance.Context.CurrentHandler == null) ? "N.A." : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
    string userIdentifier = (contextBase.ApplicationInstance != null && contextBase.ApplicationInstance.Context != null && contextBase.ApplicationInstance.Context.CurrentHandler != null && CookieManager.Exists("UserIdentifier")) ? CookieManager.Read("UserIdentifier", Guid.NewGuid().ToString().ToUpper()) : Guid.Empty.ToString();
    string requestIdentifier = (contextBase.ApplicationInstance != null && contextBase.ApplicationInstance.Context != null && contextBase.ApplicationInstance.Context.Cache != null && HttpContext.Current.Cache["RequestIdentifier"] != null) ? HttpContext.Current.Cache["RequestIdentifier"].ToString() : Guid.Empty.ToString();

    // Additional code for processing is done here.
}

Я использую HttpContextBase и интерфейс для Unit of Work, так как я знаю, что легче тестировать единицы, чем.

Теперь я использую Moq для использования функциональности Mocking в своем модульном тесте, и я борюсь с ним.

Посмотрим на переменную cliënt:

string client = (contextBase.ApplicationInstance == null || contextBase.ApplicationInstance.Context.CurrentHandler == null) ? "N.A." : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

Я хотел бы знать, как настроить мой unit тест (ы), насмехаясь над необходимыми объектами.

Здесь мой текущий unit тест:

var context = new Mock<HttpContextBase>();
var httpApplicationMock = new Mock<HttpApplication>();

httpApplicationMock.SetupGet(x => x.Context).Returns(context.Object); --> FAILS
context.SetupGet(c => c.ApplicationInstance).Returns(httpApplicationMock.Object);

Настройка httpApplicationMock не выполняется, потому что context.Object не является допустимым параметром, но мне нужно передать HttpContext.

Может кто-нибудь дать мне немного, нежный толчок в правильном направлении?

Теги:
unit-testing
mocking
moq

2 ответа

0
Лучший ответ

После некоторых дальнейших тестов я понял, что это не так.

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

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

Когда я запускаю свой первый файл с модульным тестом с указанным параметром, все шло отлично, так как все еще нужно было создать настройку.

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

Это вызвало проблему.

В любом случае, благодаря людям, которые пытались помочь мне в этой ситуации.

1

Эта строка не работает, потому что Context возвращает тип HttpContext, а не HttpContextBase.

httpApplicationMock.SetupGet(x => x.Context).Returns(context.Object);

Создание context как экземпляра Mock<HttpContext> не поможет ни потому, что он запечатанный класс, а Moq не могут высмеять закрытые классы.

Вы можете скрыть детали реализации, касающиеся HttpContext за интерфейсом. Здесь сообщение в блоге, которое показывает вам пример: http://volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext

  • 0
    Это значит, что мне нужно переписать и мой «LogManager», потому что вы хотите, чтобы я передавал интерфейс к нему (возможно, с помощью внедрения зависимостей). Это правильно?
  • 0
    @ Complexity Я не вижу ваш класс LogManager, но передача зависимостей путем внедрения обычно является хорошей идеей. Я не назвал бы это переписыванием все же.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню