0

Я никогда не запускал модульное тестирование раньше, и я просто пытаюсь запустить пример, который я нашел в сети снова и снова в отношении имени представления.Почему возникает следующая ошибка: «System.NullReferenceException: ссылка на объект не установлена ​​в экземпляр объекта». когда я запускаю модульный тест?

Мой тестовый код:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Admin.Web.API.Controllers; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Web.Mvc; 
namespace Admin.Web.API.Controllers.Tests 
{ 
    [TestClass()] 
    public class HomeControllerTests 
    { 
     [TestMethod()] 
     public void IndexTest() 
     { 
      HomeController controller = new HomeController(); 
      var result = controller.Index() as ViewResult; 
      Assert.AreEqual("Index", result.ViewName); 
     } 
    } 
} 

Ошибка я получаю System.NullReferenceException: Object reference not set to an instance of an object. на линии, которая устанавливает результат просмотра.

Что мне нужно сделать, чтобы это сработало? Есть ли что-нибудь более подробное, чем примеры тестирования модулей?

Редактировать один

Controller Код для индекса

public ActionResult Index() 
{ 
    if (this.Session["UserID"] == null) 
    { 
     return View("Login"); 
    } 
    else 
    { 
     ViewBag.Title = "Index"; 
     ViewBag.SiteID = this.Session["SiteID"]; 
     ViewBag.AssemblyVersion = this.Session["AssemblyVersion"]; 
     ViewBag.UserFirstName = this.Session["FirstName"]; 
     GoogleAnalytics _oGoogleAnalytics = new GoogleAnalytics(); 
     ViewBag.GoogleAnalytics = _oGoogleAnalytics.GetGoogleAnalytics(
      this.Session["GoogleAnalyticsAccountCode"].ToString(), 
      Convert.ToBoolean(this.Session["UseGoogleAnalytics"])); 
      return View("Index"); 
    } 
} 
+0

@AlexeiLevenkov Серьезно, можем ли мы остановиться на этом дублированном дерьме по этим вопросам? Я уверен, что OP знает, что что-то имеет значение null, но не как исправить тест, который в этом случае должен предоставить ControllerContext, чтобы дать контроллеру необходимую информацию. Проблема здесь заключается не в том, что он не знает, что такое NRE, а в том, что он не знает, как правильно настроить контроллер для модульного тестирования, потому что MVC обычно справляется с этим. – Andy

+0

@AlexeiLevenkov Я давал всю эту информацию в своем ответе, когда вы решили закрыть все это самостоятельно. В этом вопросе есть все детали, необходимые для того, чтобы кто-то, знакомый с соответствующими технологиями, ответил. – Andy

+0

@ Проблема с Энди ФП была совершенно не связана с постами в соответствии с комментарием ... Не забудьте привести вопрос в свой будущий ответ, когда закончите. –

ответ

0

controller.Index() не возвращает ViewResult и, таким образом, является resultnull.

result.ViewName не работает, поскольку вы разыскиваете null.

Вам нужно посмотреть определение Index и определить, какой тип объекта он возвращает. В качестве альтернативы вы можете создать переменную для controller.Index() и посмотреть, какой у нее тип.

EDIT:

Принимая более глубокий взгляд на Index() кажется, что вы полагаетесь на некоторых точках данных, которые могут быть не доступны. Контроллер полагается на свою структуру (в данном случае на ваш тестовый каркас), чтобы обеспечить определенные части, IIRC Session и ViewBag - две из этих частей.

+0

Как я уже сказал, я новичок во всей модульной схеме тестирования. Как мне это сделать? Что вы имеете в виду по определению индекса. Вы говорите о коде контроллера для ActionResult? Я отредактирую вопрос и добавлю код контроллера для индекса, если это поможет. –

+2

@JohnSchultz Эта проблема на самом деле не связана с модульным тестированием. Либо метод «Индекс» в классе HomeController возвращает null, либо его тип возврата не является ViewResult – Rob

+0

ОК, я прокомментировал все, кроме обратного представления и названия, и теперь он работает. Как я могу делать какие-либо тесты, если не могу определить, на какой странице Im? –

1

Вы используете свойство контроллеров Session, которое будет равно нулю, поскольку вы не предоставили контроллеру информацию, необходимую для его создания. Эта информация обычно предоставляется автоматически при работе в конвейере Asp.Net. Вы можете проверить это, отлаживая и вступая в (F11) метод действия Index и зависая над Session.

Вам необходимо установить свойство контроллера ControllerContext. Еще лучше было бы использовать атрибут Authorize для вашего метода/контроллера действия. This - хорошее сообщение о том, как сделать проверку подлинности форм в MVC.

Простейший способ получить ваш тест, однако, состоит в том, чтобы использовать . Вы также делаете это, создавая экземпляр ControllerContext и устанавливая его свойство HttpContext, возможно, Moq'ing HttpContextBase, чтобы вы могли вернуть то, что хотите, IPrincipal.

Так вот что вам нужно добавить после нового контроллера (я показываю вам схему Moq, но инструменты VS UnitTest могут предоставить свой собственный способ делать издевательства.Либо штраф):

var principalMock = new Mock<IPrincipal>(); // Mock<T> is from the Moq framework 
principalMock.Setup(x => x.IsAuthenticated).Returns(true); // Or false, depending on what you're testing 

var httpContextMock = new Mock<HttpContextBase>(); 
httpContextMock.Setup(x => x.User).Returns(principalMock.Object); 

var controllerContext = new ControllerContext { HttpContext = contextMock.Object }; 
conrollerContext.Controller = controller; 
controller.ControllerContext = controllerContext; 

После того как вы все, что установка, то можно смело назвать метод действия вы тестирования.