Проблемы насмешливые MVC ControllerContext запрос - PullRequest
0 голосов
/ 14 сентября 2009

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

Я вижу только то, что controller.ControllerContext.HttpContext.Request устанавливается при первой проверке, но каждый раз после этого Запрос равен нулю.

Это вызывает исключение пустой ссылки в методе PopulateDictionary класса * ValueProviderDictionary * в источнике MVC, так как объект запроса доступен несколько раз в этом методе, не гарантируя, что запрос не является нулевым.

Я склеиваю несколько техник и помощников, которые я нашел, исследуя, как преодолеть некоторые из проблем, с которыми я столкнулся до сих пор, поэтому на данный момент я немного не уверен, где я мог представить эту проблему.

Не правильно ли я здесь использую макеты?

Неудачный тест

//Test
public void Test_FooController_OnActionExecuting_ShouldMapStateToAFooModel()
{
    //Arrange
    DataAccessFactoryMocks.MockAllDaos();

    var controller = new FooController();

    var testFormCollection = new NameValueCollection();
    testFormCollection.Add("foo.CustomerID", "3");
    testFormCollection.Add("_fooForm", SerializationUtils.Serialize(new FooModel()));

    var mockHttpContext = new MockHttpContext(controller, "POST", testFormCollection, null);

    //Accessor used to run the protected OnActionExecuting method in my controller
    var accessor = new FooControllerAccessor(controller);

    //Request is set, assertion passes
    Assert.IsNotNull(controller.ControllerContext.HttpContext.Request.Form);

    //Request is null when accessing the property a second time, assertion fails
    Assert.IsNotNull(controller.ControllerContext.HttpContext.Request.QueryString);

    //Act
    accessor.OnActionExecuting(new ActionExecutingContext(controller.ControllerContext, MockRepository.GenerateStub<ActionDescriptor>(), new Dictionary<string, object>()));

    //Assert
    Assert.That(controller.ModelState.IsValid == false);
}

Помощник по тестированию

//Test helper to create httpcontext and set controller context accordingly
public class MockHttpContext
{
    public HttpContextBase HttpContext { get; private set; }
    public HttpRequestBase Request { get; private set; }
    public HttpResponseBase Response { get; private set; }
    public RouteData RouteData { get; private set; }

    public MockHttpContext(Controller onController)
    {
        //Setup the common context components and their relationships
        HttpContext = MockRepository.GenerateMock<HttpContextBase>();
        Request = MockRepository.GenerateMock<HttpRequestBase>();
        Response = MockRepository.GenerateMock<HttpResponseBase>();

        //Setup the context, request, response relationship
        HttpContext.Stub(c => c.Request).Return(Request);
        HttpContext.Stub(c => c.Response).Return(Response);

        Request.Stub(r => r.Cookies).Return(new HttpCookieCollection());
        Response.Stub(r => r.Cookies).Return(new HttpCookieCollection());

        Request.Stub(r => r.QueryString).Return(new NameValueCollection());
        Request.Stub(r => r.Form).Return(new NameValueCollection());

        //Apply the context to the suppplied controller
        var rc = new RequestContext(HttpContext, new RouteData());
        onController.ControllerContext = new ControllerContext(rc, onController);
    }

    public MockHttpContext(Controller onController, string httpRequestType, NameValueCollection form, NameValueCollection querystring)
    {
    //Setup the common context components and their relationships
    HttpContext = MockRepository.GenerateMock<HttpContextBase>();
    Request = MockRepository.GenerateMock<HttpRequestBase>();
    Response = MockRepository.GenerateMock<HttpResponseBase>();

    //Setup request type based on parameter value
    Request.Stub(r => r.RequestType).Return(httpRequestType);

    //Setup the context, request, response relationship
    HttpContext.Stub(c => c.Request).Return(Request);
    HttpContext.Stub(c => c.Response).Return(Response);

    Request.Stub(r => r.Cookies).Return(new HttpCookieCollection());
    Response.Stub(r => r.Cookies).Return(new HttpCookieCollection());

    Request.Stub(r => r.QueryString).Return(querystring);
    Request.Stub(r => r.Form).Return(form);

    //Apply the context to the suppplied controller
    var rc = new RequestContext(HttpContext, new RouteData());
    onController.ControllerContext = new ControllerContext(rc, onController);
    }
}

Рабочий тест с использованием MvcContrib.TestHelper

    public void Test_FooController_OnActionExecuting_ShouldMapStateToAFooModel()
    {
        //Arrange
        DataAccessFactoryMocks.MockAllDaos();

        TestControllerBuilder builder = new TestControllerBuilder();

        builder.Form.Add("fooModel.CustomerID", "3");

        builder.HttpContext.Request.Stub(r => r.RequestType).Return("POST");

        FooController controller = builder.CreateController<FooController>();

        var accessor = new FooControllerAccessor(controller);

        //Act
        accessor.OnActionExecuting(new ActionExecutingContext(controller.ControllerContext, MockRepository.GenerateStub<ActionDescriptor>(), new Dictionary<string, object>()));

        //Assert
        Assert.IsFalse(controller.ModelState.IsValid);
    }

Ответы [ 2 ]

5 голосов
/ 14 сентября 2009

Я бы посоветовал вам использовать превосходный MVCContrib TestHelper для модульного тестирования ваших контроллеров ASP.NET MVC с помощью Rhino Mocks. Вы увидите резкое упрощение ваших юнит-тестов и повышение читабельности.

0 голосов
/ 25 сентября 2015

Что я понимаю из вашего вопроса, так это то, что насмешка над ControllerContext также может быть заменена объектом-заглушкой, поскольку целью является не тестирование поведения ControllerContext. Кроме того, я не совсем уверен, зачем вам нужен FooControllerAccessor, в то время как ваша единственная задача - утвердить ModelState, поэтому я оставил это здесь:

public void Test_FooController_OnActionExecuting_ShouldMapStateToAFooModel()
{
    // Arrange
    var action = new FooController()
        .Action("index")
        .RequestData(new Dictionary<string, object>()
        {
            {"foo.CustomerID", 3},
            {"_fooForm", new FooModel()}
        });

    //Act
    var modelState = action.ValidateRequest();

    //Assert
    Assert.That(modelState.IsValid == false);
}

Чтобы использовать этот код, вы должны установить Xania.AspNet.Simulator (на момент написания v1.4.0-beta5) работает для Mvc4 и Mvc5

PM > установочный пакет Xania.AspNet.Simulator -Pre

Для дополнительных примеров проверьте следующее:

...