Я пытаюсь проверить поведение моего приложения ASP.Net MVC при непредвиденной ошибке. В частности, я пытаюсь убедиться, что пользователь перенаправлен на страницу с ошибкой, которую я определил для своего приложения. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу проверить поведение метода контроллера, как ожидалось.
Для моих обычных тестов поведения я создаю объект фиктивного бизнес-правила и передаю его контроллеру, а затем проверяю ViewResult из метода контроллера, который я хочу протестировать. Это прекрасно работает для моих целей, когда все работает как положено. Однако , когда я выкидываю исключение из метода бизнес-правила, исключение передается через результат метода контроллера , а не обрабатывается (метод контроллера имеет атрибут 'HandleError') контроллером, чтобы был возвращен соответствующий ViewResult для моей страницы ошибки.
Есть ли способ проверить поведение атрибута HandleError таким образом? Или я иду по этому поводу совершенно неправильно? Я понимаю, что мог бы использовать Selenium (тестирование в браузере, которое попадало бы на реальный сервер), чтобы проверить поведение в реальном браузере, но насмешливые подобные тесты позволяют мне делать это быстрее и с гораздо меньшими накладными расходами ...
Пример тестового кода:
// WidgetController.Index() makes a call to GetWidgets to retrieve a
// List<Widget> instance.
// this works as expected since the appropriate ViewResult is returned
// by the controller
public void TestWidgetControllerIndex_NoResultsFound()
{
var mockBR = new Mock<IBusinessRules> { CallBase = true };
mockBR.Setup(br=>fr.GetWidgets()).Returns(new List<Widget>());
WidgetController controller = new WidgetController(mockBR.Object);
ViewResult result = (ViewResult)controller.Index();
Assert.AreEqual("Index", result.ViewName);
Assert.AreEqual(0,
((WidgetIndexViewData)result.ViewData.Model).Widgets.Count);
}
// this test is unable to reach the assertion statements due to the problem
// outlined above. WidgetController.Index has the HandleError attribute
// properly applied and the behaviour via the interface is as expected
public void TestWidgetControllerIndex_BusinessRulesExceptionEncountered()
{
var mockBR = new Mock<IBusinessRules> { CallBase = true };
mockBR.Setup(br=>fr.GetWidgets()).Throws<ApplicationException>();
WidgetController controller = new WidgetController(mockBR.Object);
ViewResult result = (ViewResult)controller.Index();
// The ApplicationException thrown by the business rules object bubbles
// up to the test through the line above. I was expecting this to be
// caught and handled by the HandleError filter (which would then let
// me verify the behaviour results via the assertion below)..
Assert.AreEqual("Error", result.ViewName);
}
Буду признателен за любые предположения относительно того, что я могу делать неправильно или же я просто подхожу к этому с совершенно неправильного направления. Я делаю предположение, что тестирование на уровне метода контроллера является подходящим способом, так как именно здесь применяется атрибут HandleError .. (Если мне нужно протестировать на уровне приложения, возможно ли это сделать с помощью аналогичного инстанцированные объекты вместо использования чего-то вроде Selenium?)
Обновление
Я пришел к выводу, что не следует тестировать функциональность, связанную с атрибутом HandleError, в каждом действии контроллера. На самом деле меня не волнует, что он делает, я просто хочу убедиться, что ошибка обработана (с точки зрения моего теста, независимо от того, имеет ли значение его пользовательский код или библиотеки MVC, это функциональность, которую я хочу проверить ).
В итоге я обернул действия моего контроллера в блоки try / catch, чтобы принудительно вернуть представление Error в результате метода (а не атрибут ErrorHandler, перехватывающий ошибку при выходе из метода). ). Таким образом, я могу утверждать в своих модульных тестах, что ошибка правильно обрабатывается с соответствующей обратной связью. Я не очень доволен дополнительной длиной, которую это добавляет к моим методам контроллера, но она позволяет мне предоставить дружественное, конкретное сообщение об ошибке пользователю (я использую метод расширения, чтобы отобразить обратную связь и выполнить регистрацию). (Так что у подхода «попробуй / поймай» есть плюсы и минусы ..)
Я не уверен на 100%, что это самый чистый путь, но он достигает моей цели - иметь возможность проверить, что ошибки обрабатываются с помощью модульных тестов контроллера (быстро), а не выполнять тесты в браузере. (медленный). В общем, пока это достаточно , пока я не найду более чистого решения. Я решил предложить вознаграждение, если кто-то сталкивается с подобной проблемой и нашел лучшее решение.