Как правильно смоделировать мой контроллер контекста для проверки ViewResult.ExecuteResult ()? - PullRequest
6 голосов
/ 17 мая 2011

Я пытаюсь создать интеграционные тесты, чтобы убедиться, что в моих представлениях нет ошибок времени выполнения. Поэтому мне нужно создать тест, который проверяет, правильно ли работает ViewResult.ExecuteResult(), но, похоже, я столкнулся с проблемой.

Я нашел этот сайт , который дал мне отправную точку, и у меня есть следующий код:

    [TestMethod]
    public void RegisterResultExecutes()
    {
        //arrange 
        RequestContext requestContext = new RequestContext(new MockHttpContext(), new RouteData());
        AccountController controller = new AccountController
        {
            FormsService = new MockFormsAuthenticationService(),
            MembershipService = new MockMembershipService(),
            Url = new UrlHelper(requestContext)
        };

        var result = controller.Register();
        var sb = new StringBuilder();
        Mock<HttpResponseBase> response = new Mock<HttpResponseBase>();
        response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y =>
        {
            sb.Append(y);
        });
        Mock<ControllerContext> controllerContext = new Mock<ControllerContext>();
        controllerContext.Setup(x => x.HttpContext.Response).Returns(response.Object);

        //act 
        result.ExecuteResult(controllerContext.Object);
    }

Проблема в том, что когда вызывается result.ExecuteResult(), я получаю следующее исключение

System.NullReferenceException: Object reference not set to an instance of an object.

System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
MyApp.Tests.Controllers.AccountControllerTest.RegisterResultExecutes() in C:\Users\KallDrexx\Documents\Projects\MyApp\MyApp.Tests\Controllers\AccountControllerTests.cs: line 297

К сожалению, эта трассировка стека не очень полезна, так как я не уверен, что он пытается получить доступ, что является нулевым. У кого-нибудь есть предложения по созданию теста для ExecuteResult()?

Ответы [ 2 ]

4 голосов
/ 17 мая 2011

На основе трассировки стека это что-то в методе ViewResultBase.ExecuteResult, которое выдает исключение.Используя рефлектор, вот определение этого метода:

public override void ExecuteResult(ControllerContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context");
    }
    if (string.IsNullOrEmpty(this.ViewName))
    {
        this.ViewName = context.RouteData.GetRequiredString("action");
    }
    ViewEngineResult result = null;
    if (this.View == null)
    {
        result = this.FindView(context);
        this.View = result.View;
    }
    TextWriter output = context.HttpContext.Response.Output;
    ViewContext viewContext = new ViewContext(context, this.View, this.ViewData, this.TempData, output);
    this.View.Render(viewContext, output);
    if (result != null)
    {
        result.ViewEngine.ReleaseView(context, this.View);
    }
}

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

Исключение может быть вызвано путем доступа к свойству HttpContext.Я недостаточно хорошо использовал Moq, чтобы понять, может ли он справиться с тем фактом, что вы не сказали ему, как имитировать свойство HttpContext, но вы сказали ему, как имитировать свойство Response из HttpContextТип свойства, так что это еще одна область, которая вызывает у меня подозрение.

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

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

1 голос
/ 20 марта 2012

Я столкнулся с той же проблемой, что и сейчас, и решил ее, установив HttpContext.Current.

Попробуйте добавить следующее в код модульного теста: например,

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://mock", ""),
    new HttpResponse(new StringWriter()));

Одна вещь, которую я нашел полезной для отладки такого рода проблем вместо использования отражателя или ILSpy, - это включение символов отладки для кода платформы .Net. Таким образом, вы можете присоединиться к вашему процессу NUnit и точно увидеть, какая строка кода вызывает исключение и, следовательно, что вам нужно для проверки в тесте.

Шон Берк написал отличную статью в блоге, подробно рассказывающую, как это настроить: http://blogs.msdn.com/b/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

...