Модульное тестирование моего метода контроллера приводит к пустому ViewName? - PullRequest
27 голосов
/ 05 апреля 2009

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

Когда я проверяю свойство ViewName, из возвращенного объекта ViewResult это "" (пусто).

У меня сложилось впечатление, что ViewName подразумевается именем View (как , предложенное в этой статье MS о тестировании контроллера ASP.NET MVC).

Кстати, когда я тестирую ViewData, все там и правильно.

Вот код, который у меня есть ...

public ActionResult Index(int? page, string tag)
{
    if (page == null || page <= 0)
    {
        page = 1;
    }

    var viewData = new IndexViewData
                       {
                       ... my property setters, etc ...
                       };
    return View(viewData);
}

[TestMethod]
public void Index_Action_Should_Return_Index_View_For_Default_HomePage()
{
    // Arrange.
    var controller = PostController; // Wrapper, cause I use D.I.

    // Act.
    ViewResult viewResult = controller.Index(null, null) as ViewResult;

    // Assert.
    Assert.IsNotNull(viewResult);
    Assert.AreEqual("Index", viewResult.ViewName); // This is false/fails.

    var indexViewData = viewResult.ViewData.Model as IndexViewData;
    Assert.IsNotNull(indexViewData); // This is true.
}

Ответы [ 4 ]

28 голосов
/ 05 апреля 2009

ViewName присутствует только тогда, когда вы устанавливаете его в ViewResult. Если имя вашего View совпадает с именем вашего контроллера, то я бы проверил, чтобы ViewName было пустым или пустым, поскольку это (IMO) - правильное поведение, так как вы не хотите устанавливать имя в представлении. Я проверяю только то, что ViewName установлено, когда я предполагаю, что возвращаемое представление не соответствует действию, например, при возврате представления «Ошибка».

EDIT : ниже приведен источник для ExecuteResult в ViewResultBase.cs (из RC1 у меня нет источника для RTW на моем Macintosh). Как вы можете видеть, он проверяет, было ли ViewName установлено напрямую, а если нет, он извлекает его из действия в данных маршрута контекста контроллера. Это происходит только в ExecuteResult, который вызывается ПОСЛЕ того, как действие вашего контроллера завершено.

    public override void ExecuteResult(ControllerContext context) {
        if (context == null) {
            throw new ArgumentNullException("context");
        }
        if (String.IsNullOrEmpty(ViewName)) {
            ViewName = context.RouteData.GetRequiredString("action");
        }

        ViewEngineResult result = null;

        if (View == null) {
            result = FindView(context);
            View = result.View;
        }

        ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
        View.Render(viewContext, context.HttpContext.Response.Output);

        if (result != null) {
            result.ViewEngine.ReleaseView(context, View);
        }
    }
2 голосов
/ 07 декабря 2010

Мне лично показалось, что средства тестирования, предоставляемые MVC2, несколько неуклюжи. Я предполагаю, что что-то лучше уже существует, но в итоге я создал простой класс для тестирования действий. Я смоделировал интерфейс (реализация - другая история) для класса, предоставленного превосходным открытым исходным кодом Java MVC Framework Stripes , названным MockRoundTrip.

Вот метод, используемый для получения страницы назначения действия при тестировании действий, который называется getTripDestination(). Он возвращает правильный результат независимо от того, задано ли явно имя представления или нет

    //Get the destination page of the request, using Runtime execution pattern of MVC, namely
    //if no ViewName is explicitly set in controller, ViewResult will have an empty ViewName
    //Instead, current action name will be used in its place
    public string getTripDestination()
    {
       RouteData routeData = getRouteData();
       ViewResult viewResult = (result is ViewResult) ? (ViewResult)result : null;
       string tripDestination = (viewResult != null) ? viewResult.ViewName : "";

       return (tripDestination != "") ? tripDestination : (String)routeData.Values["action"];
    }

    private RouteData getRouteData()
    {
       HttpContextBase context = controller.ControllerContext.RequestContext.HttpContext;
       return RouteTable.Routes.GetRouteData(context);
    }
0 голосов
/ 15 июня 2016

Документация для Controller.View () гласит:

Эта перегрузка метода класса View возвращает объект ViewResult. который имеет пустое свойство ViewName . Если вы пишете юнит-тесты для действия контроллера, учитывайте пустое свойство ViewName для модульные тесты, которые не принимают имя строкового представления.

Во время выполнения, если свойство ViewName пустое, текущее действие имя используется вместо свойства ViewName.

Так что, ожидая представления с тем же именем, что и текущее действие, мы можем просто проверить, что это пустая строка.

В качестве альтернативы метод Controller.View (String) устанавливает ViewName.

0 голосов
/ 25 апреля 2009

Имя представления устанавливается автоматически рамкой. Но когда мы проводим модульное тестирование, мы закорачиваем фреймворк, и нам не остается ничего, чтобы установить имя.

Таким образом, наши действия должны явно указывать имя представления, когда мы тестируем модуль. Мы также могли бы проверить на ноль или пусто, если мы действительно, действительно хотим опираться на соглашение.

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