Как сделать модульный тест для проверки метода, который проверяет заголовки запросов?

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

public class myClass : RequireHttpsAttribute
{
    public override void OnAuthorization(AuthoizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var header = Convert.ToBoolean(request.Headers["Special-Header-Name"]);

        if (!(header || request.IsSecureConnection))
        {
            HandleNonHttpsRequest(filterContext);
        }
    }
}

Этот метод, который наследуется от RequireHttpsAttributeпроверяет, присутствует ли на странице определенный заголовок, отсутствует ли он или имеет значение "ложь", а также не является ли страница небезопасной, HandleNonHttpsRequestв противном случае это ничего не делает.

Мы используем Moq и Nunit для тестирования. Я нашел некоторые ресурсы, чтобы помочь создать fakeHttpContext с Moq, но, честно говоря, я не уверен, как его использовать или куда идти в рамках моих модульных тестов, чтобы убедиться, что поддельные HttpContexts являются или не вызывают HandleNonHttpsRequest метод для вызова.

Я действительно ценю любые рекомендации по этому вопросу.

3 ответа

Решение
// arrange
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var headers = new NameValueCollection
{
    { "Special-Header-Name", "false" }
};
request.Setup(x => x.Headers).Returns(headers);
request.Setup(x => x.HttpMethod).Returns("GET");
request.Setup(x => x.Url).Returns(new Uri("http://www.example.com"));
request.Setup(x => x.RawUrl).Returns("/home/index");
context.Setup(x => x.Request).Returns(request.Object);
var controller = new Mock<ControllerBase>();

var actionDescriptor = new Mock<ActionDescriptor>();
var controllerContext = new ControllerContext(context.Object, new RouteData(), controller.Object);
var filterContext = new AuthorizationContext(controllerContext, actionDescriptor.Object);
var sut = new myClass();

// act
sut.OnAuthorization(filterContext);

// assert
Assert.IsInstanceOfType(filterContext.Result, typeof(RedirectResult));
var redirectResult = (RedirectResult)filterContext.Result;
Assert.AreEqual("https://www.example.com/home/index", redirectResult.Url);

Да, я бы использовал Moq и создал бы Mock<AuthorizationContext>, Вам понадобится серия фиктивных объектов для настройки поддельного запроса, прежде всего для указания NameValueCollection поддельных заголовков.

var request = new Mock<HttpRequestBase>();
request.SetupGet(c => c.Headers).Return(new NameValueCollection{ /* initialize values here */});
request.SetupGet(c => c.IsSecureConnection).Return(/*specify true or false depending on your test */);

var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Return(request.Object);


var filterContext = new Mock<AuthorizationContext>();
filterContext.SetupGet(c => c.HttpContext).Return(httpContext.Object);

var myclass = new myClass();
myClass.OnAuthorization(filterContext.Object);

(извините, если синтаксис или использование немного отключены; делаю это из головы)

Вам может потребоваться войти и смоделировать любые дополнительные члены в filterContext, которые вызывает HandleNonHttpsRequest. У меня есть две рекомендации для этого, так как иногда может возникнуть проблема, если метод, который вы тестируете, делает много сложных вещей в filterContext: 1) проверять визуально и, если это достаточно просто, высмеивать все вызываемые части 2) создайте myClass.OnAuthorizationRequest, но не реализуйте никакого кода, кроме вызова HandleNonHttpsRequest. Продолжайте выполнять тестирование и исправляйте отсутствующие / неправильно проверенные элементы до тех пор, пока тест не пройдет. Затем реализуйте свою фактическую логику для OnAuthorizationRequest, тестируя и исправляя (повтор ополаскивания), пока он не пройдет.

Я столкнулся с проблемой с принятым решением с использованием ASP.NET MVC 4. Чтобы решить его, я издевался над атрибутом элементов контекста http, в противном случае sut.OnAuthorization Вызывает объект неопределенное исключение:

MockHttpContext.Setup(x => x.Items)
    .Returns(new System.Collections.Generic.Dictionary<object, object>());
Другие вопросы по тегам