asp.net mvc Как правильно тестировать контроллеры - PullRequest
5 голосов
/ 18 июня 2010

У меня проблемы с тестированием контроллеров. Оригинальный мой контроллер для тестирования выглядел примерно так:

SomethingController CreateSomethingController()
{
    var somethingData = FakeSomethingData.CreateFakeData();
    var fakeRepository = FakeRepository.Create();

    var controller = new SomethingController(fakeRepository);

    return controller;
}

Это нормально работает для большинства тестирований, пока я не получу часть кода Request.IsAjaxRequest(). Тогда мне пришлось создать макет HttpContext и HttpRequestBase. Поэтому мой код изменился и теперь выглядит так:

public class FakeHttpContext : HttpContextBase
{
    bool _isAjaxRequest;

    public FakeHttpContext( bool isAjaxRequest = false )
    {
        _isAjaxRequest = isAjaxRequest;
    }

    public override HttpRequestBase Request
    {
        get
        {
            string ajaxRequestHeader = "";

            if ( _isAjaxRequest )
                ajaxRequestHeader = "XMLHttpRequest";

            var request = new Mock<HttpRequestBase>();
            request.SetupGet( x => x.Headers ).Returns( new WebHeaderCollection 
            {
                {"X-Requested-With", ajaxRequestHeader} 
            } );

            request.SetupGet( x => x["X-Requested-With"] ).Returns( ajaxRequestHeader );

            return request.Object;
        }
    }

    private IPrincipal _user;

    public override IPrincipal User
    {
        get
        {
            if ( _user == null )
            {
                _user = new FakePrincipal();
            }
            return _user;
        }
        set
        {
            _user = value;
        }
    }
}


SomethingController CreateSomethingController()
{
    var somethingData = FakeSomethingData.CreateFakeData();
    var fakeRepository = FakeRepository.Create();

    var controller = new SomethingController(fakeRepository);

    ControllerContext controllerContext = new ControllerContext( new FakeHttpContext( isAjaxRequest ), new RouteData(), controller );
     controller.ControllerContext = controllerContext;

    return controller;
}

Теперь он дошел до той стадии в моем контроллере, где я называю Url.Route, а Url - ноль. Похоже, мне нужно начать макетирование маршрутов для моего контроллера.

Кажется, я трачу больше времени на поиск того, как подделать / смоделировать объекты, а затем отладить, чтобы убедиться, что мои подделки верны, чем фактическое написание тестового кода. Есть ли более простой способ проверить контроллер? Я посмотрел на TestControllerBuilder от MvcContrib, который помогает с некоторыми проблемами, но, кажется, не делает все. Есть ли что-нибудь еще, что выполнит эту работу и позволит мне сосредоточиться на написании тестов, а не на издевательствах?

Спасибо

Ответы [ 4 ]

1 голос
/ 18 июня 2010

Вместо насмешек вы можете передать IAjaxRequest в конструктор. Или сделайте его базовым свойством класса конструктора (и используйте инъекцию свойства). Или вы можете заставить свой конструктор реализовать IAjaxRequest, а затем применить глобальный фильтр действий к базовому классу конструктора, который установит IAjaxRequest.

Это поможет абстрагироваться от многих вещей, в том числе от HttpContext. Только не абстрагируйте IHttpContext, абстрагируйте IUserContext, ISessionStorage, IAuthentication, IRequestDetails ...

Другой способ - использовать связыватель модели непосредственно в методах, где вам нужна конкретная информация. Смотрите этот пост например. Вы можете сделать связыватель, который даст вам IsAjaxRequest, а затем просто сделать действие, чтобы принять этот параметр. Работает очень хорошо, потому что информация предоставляется именно тому методу, который нуждается в ней, а не всему контроллеру.

1 голос
/ 18 июня 2010

Самый насмешливый движок сделает все это за вас.Я использую RhinoMocks , но их гораздо больше.Также Кроты - это очень новый и интересный движок для насмешек (обычно он поставляется с Pex, который еще больше боеприпасов в вашем арсенале юнит-тестирования)

1 голос
/ 18 июня 2010

MvcContrib + RhinoMocks. Проверьте TestControllerBuilder в библиотеке MvcContrib.TestHelper. Вот официальное описание: http://mvccontrib.codeplex.com/wikipage?title=TestHelper#Examples.

Вот пример макетирования контроллера для тестирования UrlHelper: ASP.NET MVC: Mock controller.Url.Action

Вот краткое объяснение того, как использовать TestControllerBuilder: http://codebetter.com/blogs/kyle.baley/archive/2008/03/19/testcontrollerbuilder-in-mvccontrib.aspx

1 голос
/ 18 июня 2010

Вы можете использовать некоторые библиотеки, которые предоставляют вам некоторые из этих объектов. Например RhinoMock , NMock ... и т. Д. Я лично использую Moq - это достаточно хорошо и бесплатно. Что мне больше всего нравится в Moq, так это выражения linq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...