2013-06-08 2 views
0

Я разрабатываю приложение MVC и пытаюсь создать в нем единичный тест.Ошибка в модульном тесте подробно в MVC App

Я написал модульный тест, как показано ниже.

[TestMethod] 
     public void Company_Details2() 
     { 
      Company oCompany = new Company(); 
      var result = oCompanyController.Details(97) as ViewResult; 
      var Comp = (Company)result.ViewData.Model; 
      Assert.AreEqual("TName", Comp.Name); 

     } 

и контроллер выглядит следующим образом:

[SessionFilterAction] 
public ViewResult Details(int id) 
{ 
    Company company = db.Companies.Find(id); 
    return View(company); 
} 

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

объекта не установлен в экземпляр объекта.

Как я новичок в модульном тестировании, я не знаю, как написать методы тестирования для индексирования, создания, редактирования, сведений и методов удаления, где я могу его найти?

ответ

1

Есть много мест, где NRE может появиться в вашем коде. Например, переменная db, которая используется в действии вашего контроллера, может быть нулевой. Убедитесь, что он инициализирован. Также в вашем модульном тесте вы имеете следующий вызов: var Comp = (Company)result.ViewData.Model;. Это может быть null, если в вашей базе данных нет компании с id = 97. И затем вы пытаетесь сравнить имя Assert.AreEqual("TName", Comp.Name);. Но если Comp имеет значение null, это вызовет исключение. Также в вашем модульном тестировании вы используете переменную oCompanyController, которая неясна, где она была инициализирована.

Правильный способ модульного тестирования какого-либо кода состоит в том, чтобы блок тестировал его изолированно. Это означает, что ваш код должен быть написан с учетом абстракций. Это не должно зависеть от фактических реализаций. Неясно, какая переменная db находится в вашем контроллере, но она должна быть некоторого типа интерфейса (или абстрактного класса), который вы могли бы высмеять в своем модульном тесте. Таким образом, вы достигнете модульного тестирования в изоляции разных слоев. В этом примере вы тестируете блок управления контроллером, поэтому код в этом контроллере не должен зависеть от конкретных классов.

Давай пример того, как ваш контроллер код может выглядеть следующим образом:

public class CompaniesController: Controller 
{ 
    public readonly ICompaniesRepository repository; 
    public CompaniesController(ICompaniesRepository repository) 
    { 
     this.repository = repository; 
    } 

    [SessionFilterAction] 
    public ViewResult Details(int id) 
    { 
     Company company = this.repository.GetCompanyById(id); 
     return View(company); 
    } 
} 

Теперь вы можете использовать насмешливые рамки, такие как MOq, NSubstitute или Rhino.Mocks издеваться хранилищем в тестовом модуле и быть способный определять ожидания. Например, с NSubstitute:

[TestMethod] 
public void Company_Details2() 
{ 
    // arrange 
    var repository = Substitute.For<ICompaniesRepository>(); 
    var id = 97; 
    var company = new Company(); 
    repository.GetCompanyById(id).Returns(company); 
    var sut = new CompaniesController(repository); 

    // act 
    var actual = sut.Details(id); 

    // assert 
    Assert.IsInstanceOfType(actual, typeof(ViewResult)); 
    var viewResult = (ViewResult)actual; 
    Assert.AreEqual(company, viewResult.Model); 

} 
+0

Спасибо Дарин, но я совершенно не осведомлен о ICompaniesRepository и модах ... Что это такое? – bnil

+0

Будет хорошо, если я получу изменения, которые я должен внести в свой текущий код. – bnil

+0

Вы ожидаете, что я расскажу вам об изменениях в вашем текущем коде, не показывая ваш текущий код? То, что вы показали, представляет собой лишь небольшую часть кода. Идея заключается в использовании интерфейса, который будет абстрагировать все операции доступа к данным, чтобы ваш контроллер не был тесно связан с конкретным поставщиком доступа к данным.Если вы не знаете, что такое интерфейс, я бы очень сильно предложил вам прочитать некоторые базовые учебные пособия в .NET/C# перед тем, как попасть в ASP.NET MVC. –

0

Как показали другие, это хорошая практика кодирования интерфейса. Moq - это основа, которая поможет вам сделать фальшивый призыв к требуемым функциям и очень проста в изучении. Теперь я Предположим, что вы звоните, IRepository.Detials(), так что теперь,

[TestMethod] 
SomeMethod() 
{ 
// This will create a fake/mock for your interface so that you can still call func. 
// but not actual one. 
    Mock<IRepository> mockedRepository= new Mock<IRepository>(); 

// Here, we are making fake call but still Returns will give us the output. 
    mockedRepository.SetUp(x=>x.Details()).Returns(Company Object); 
    var result=controller.Action() as ViewResult; 
    // Assert 
} 

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

Смежные вопросы