2010-05-22 7 views
0

Я отредактировал и упростил этот вопрос.Почему этот тест модуля asp.net mvc терпит неудачу?

Если у меня есть этот метод на моем HomeController:

public ActionResult Strangeness(int id) 
    { 
     StrangenessClass strangeness = null; 

     if(id == 1) 
     { 
      strangeness = new StrangenessClass() { Name="Strangeness", Desc="Really weird behavior" }; 
     } 

     return View(strangeness); 
    } 

И есть этот класс:

public class StrangenessClass 
{ 
    public string Name { get; set; } 
    public string Desc { get; set; } 
} 

Почему этот тест устройство не может?

[TestMethod] 
    public void Strangeness() 
    { 
     HomeController controller = new HomeController(); 

     ViewResult result = controller.Strangeness(1) as ViewResult; 
     var model = result.ViewData.Model; 
     result = controller.Strangeness(2) as ViewResult; 
     model = result.ViewData.Model; 

     Assert.IsNull(model); 
    } 

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

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

ответ

1

Вы не должны повторно использовать контроллер для обработки нескольких запросов, что именно то, что вы здесь делаете.

Во всяком случае, если вы проверите source code for MVC вы найдете причину этого поведения:

protected internal virtual ViewResult View(string viewName, string masterName, object model) 
{ 
    if (model != null) 
    { 
     base.ViewData.Model = model; 
    } 
    return new ViewResult { ViewName = viewName, MasterName = masterName, ViewData = base.ViewData, TempData = base.TempData }; 
}

Если модель имеет нулевое значение, это не присваивается свойству ViewData.Model. Если вы хотите получить правильное поведение, создайте новый контроллер для вашего второго звонка до HomeController.Strangeness.

0

Непонятно, что вы тестируете. В разделе «Упорядочить» вашего тестового метода вы вызываете первое действие «Удалить», а в разделе «Действие» вы вызываете второй. Так вы тестируете контроллер? Если да, то почему вы вызываете первый метод Delete в разделе «Упорядочить»?

Также что такое переменная _stateService? Является ли это интерфейсом или вы фактически удаляете записи в базе данных вашего теста unit/integration?

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

Предполагая, что _stateService представляет собой интерфейс, который может быть издевались, который, как я рекомендовал бы вам создать свой контроллер, ваш тест может выглядеть следующим образом (с помощью Rhino Mocks и MVCContrib.TestHelper):

[TestClass] 
public class DevisControllerTests : TestControllerBuilder 
{ 
    private HomeController _sut; // Subject Under Test 
    private IStateService _stateServiceStub; // Dependency of the SUT 

    [TestInitialize()] 
    public void MyTestInitialize() 
    { 
     _stateServiceStub = MockRepository.GenerateStub<IStateService>(); 
     _sut = new HomeController(_stateServiceStub); 
     InitializeController(_sut); // this method comes from the base class TestControllerBuilder 
    } 

    [TestMethod] 
    public void HomeController_Delete_Action_Should_Fetch_State_From_Db_And_Pass_It_To_The_View() 
    { 
     // arrange 
     var id = 4; 
     var expectedState = new State(); 
     _stateServiceStub.Stub(x => x.GetById(id)).Return(expectedState); 

     // act 
     var actual = _sut.Delete(id); 

     // assert 
     actual 
      .AssertViewRendered() 
      .WithViewData<State>() 
      .ShouldBe(expectedState); 
    } 

    [TestMethod] 
    public void HomeController_Delete_Action_Handler_Should_Return_Default_View_If_Model_Null() 
    { 
     // act 
     var actual = _sut.Delete(null); 

     // assert 
     actual.AssertViewRendered(); 
    } 

    [TestMethod] 
    public void HomeController_Delete_Action_Handler_Should_Return_View_If_Exception_Thrown_From_Service() 
    { 
     // arrange 
     var model = new State(); 
     _stateServiceStub.Stub(x => x.Delete(model)).Throw(new Exception("oops")); 

     // act 
     var actual = _sut.Delete(state); 

     // assert 
     actual 
      .AssertViewRendered() 
      .WithViewData<State>() 
      .ShouldBe(model); 
    } 


    [TestMethod] 
    public void HomeController_Delete_Action_Handler_Should_Redirect_If_Model_Successfully_Deleted() 
    { 
     // arrange 
     var model = new State(); 

     // act 
     var actual = _sut.Delete(state); 

     // assert 
     actual 
      .AssertActionRedirect() 
      .ToAction<HomeController>(c => c.Index()); 

     _stateServiceStub.AssertWasCalled(x => x.Delete(model)); 
    } 

} 
+0

Есть два метода удаления контроллера, которые я опубликовал. Первый для извлечения состояния, подлежащего удалению, и второго метода post для фактического удаления. Переменная _stateService - это экземпляр моей государственной службы, основанный на интерфейсе и отменяющий все на FakeStateRepoditory для модульного тестирования. Мой TestInitialize устанавливает все это, поэтому у меня есть данные для каждого теста. Аранжировка получает запись, которую я хочу удалить, действие пытается удалить ее, а затем снова извлечь ее, а актив удостоверяется, что она равна нулю и что мы были отправлены обратно в метод Index. –

+0

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

+0

При попытке использовать ваш метод я получаю следующую ошибку в тесте HomeController_Delete_Action_Handler_Should_Redirect_If_Model_Successfully_Delete: Не удалось найти параметр с именем «controller» в коллекции значений результата. Если я изменю его на: действительный .AssertActionRedirect() .ToAction («Index»); он работает. Но я предпочитаю ваш метод. Вы знаете, что я делаю неправильно? –

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