Как сделать модульный тест для проверки метода, который проверяет заголовки запроса? - PullRequest
12 голосов
/ 13 февраля 2012

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

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 ]

20 голосов
/ 13 февраля 2012
// 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);
1 голос
/ 13 февраля 2012

Да, я бы использовал 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, тестируя и исправляя (повтор ополаскивания), пока он не пройдет.

0 голосов
/ 02 июля 2013

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

MockHttpContext.Setup(x => x.Items)
    .Returns(new System.Collections.Generic.Dictionary<object, object>());
...