Модульное тестирование (unit test) очень важная часть современной разработки программного обеспечения. При тестировании web-приложений разработчики стараются охватить все аспекты работы приложения от получения запроса до выдачи результата. При разработке проектов с помощью ASP.NET MVC одним из таких моментов является механизм маршрутизации. Тестирование маршрутов обычно приносило немало головной боли, заставляя разработчика писать много сопутствующего кода. В этой заметке я покажу как используя пару инструментов можно упростить тестирование маршрутов до минимума.
Для начала нам понадобятся следующие инструменты:
Установите NUnit, после этого добавьте в свой проект ссылки на сборки nunit.framework (из GAC), Rhino.Mocks и MvcContrib.TestHelper.
Среда готова для создания модульных тестов для маршрутов.
Для того, чтобы показать примеры модульных тестов для маршрутов, давайте определим пару таких маршрутов:
Обратите внимание на маршрут ProductList. Он содержит ограничение YearConstraint, код которого я пропущу, но скажу только, что это ограничение проверяет параметр year на принадлежность диапазону от 1900 до 2100.
Для тестирования создадим следующий класс:
Для тех, кто работал с NUnit ранее атрибуты будут знакомыми, остальным немножко расскажу про их назначение:
Здесь, с использованием методов расширения библиотеки MvcContrib мы проверяем на работоспособность запрос к корню проекта, который согласно определенным нами маршрутам, должен маршрутизироваться с помощью маршрута Default. Этот маршрут создается в ASP.NET MVC-приложениях по умолчанию. Запрос к корню проекта по умолчанию должен маршрутизироваться в выполнение действия Index контроллера HomeController.
Скомпилируем проект и запустим NUnit. Выбрав в качестве проекта нашу сборку с тестом нажмем Run для запуска теста. Результат на картинке ниже:
Тест пройден. Добавим остальные тесты:
Здесь представлено четыре теста:
И последнее на что стоит обратить внимание – это то, как легко создается тест для проверки маршрутов игнорирования. Метод расширения ShouldBeIgnored позволяет задать тест для таких маршрутов. В нашем тесте TestIgnoreAxd мы пытаемся представить ситуацию с обращением к некоему axd-ресурсу, которое, согласно заданным маршрутам должно игнорироваться.
Скомпилируем и запустим тесты в NUnit:
Все тесты пройдены. Работа сделана.
В этой статье я рассмотрел простейшие варианты тестов для модульного тестирования маршрутов в ASP.NET MVC. Инструменты, которые представлены в библиотеке MvcContrib позволяют очень просто создавать такие тесты и, безусловно, облегчают жизнь разработчику.
Для своих проектов, вероятно, вы захотите создать более подробные модульные тесты работы механизма маршрутизации. В этом вам поможет MvcContrib. Программируйте с удовольствием!
Инструменты
Для начала нам понадобятся следующие инструменты:
- MvcContrib – библиотека с дополнительным для ASP.NET MVC функционалом, в том числе в области модульного тестирования;
- RhinoMocks – библиотека для создания фальшивых (mock) объектов упрощающих тестирование;
- NUnit – среда модульного тестирования с набором собственных атрибутов и инструментов.
Установка
Установите NUnit, после этого добавьте в свой проект ссылки на сборки nunit.framework (из GAC), Rhino.Mocks и MvcContrib.TestHelper.
Среда готова для создания модульных тестов для маршрутов.
Тесты
Для того, чтобы показать примеры модульных тестов для маршрутов, давайте определим пару таких маршрутов:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Product",
"Product/{id}",
new { controller = "Product", action = "GetById" }
);
routes.MapRoute("ProductList",
"ProductList/{year}",
new { controller = "Product", action = "List" },
new { year = new YearConstraint() }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
* This source code was highlighted with Source Code Highlighter.
Обратите внимание на маршрут ProductList. Он содержит ограничение YearConstraint, код которого я пропущу, но скажу только, что это ограничение проверяет параметр year на принадлежность диапазону от 1900 до 2100.
Для тестирования создадим следующий класс:
namespace Routing
{
using MvcContrib.TestHelper;
using NUnit.Framework;
using Routing.Controllers;
using System.Web.Routing;
using Rhino.Mocks;
using System.Web;
[TestFixture]
public class TestRoutes
{
[TestFixtureSetUp]
public void SetUp()
{
MvcApplication.RegisterRoutes(RouteTable.Routes);
}
[TestFixtureTearDown]
public void TearDown()
{
RouteTable.Routes.Clear();
}
}
}
* This source code was highlighted with Source Code Highlighter.
Для тех, кто работал с NUnit ранее атрибуты будут знакомыми, остальным немножко расскажу про их назначение:
- TestFixture – определяет класс с тестами;
- TestFixtureSetUp – определяет метод с кодом, который нужно выполнить перед запуском тестов;
- TestFixtureTearDown – определяет метод с кодом, который нужно выполнить после запуска тестов.
[Test]
public void TestSimpleRoute()
{
"~/".Route().ShouldMapTo<HomeController>(x => x.Index());
}
* This source code was highlighted with Source Code Highlighter.
Здесь, с использованием методов расширения библиотеки MvcContrib мы проверяем на работоспособность запрос к корню проекта, который согласно определенным нами маршрутам, должен маршрутизироваться с помощью маршрута Default. Этот маршрут создается в ASP.NET MVC-приложениях по умолчанию. Запрос к корню проекта по умолчанию должен маршрутизироваться в выполнение действия Index контроллера HomeController.
Скомпилируем проект и запустим NUnit. Выбрав в качестве проекта нашу сборку с тестом нажмем Run для запуска теста. Результат на картинке ниже:
Тест пройден. Добавим остальные тесты:
[Test]
public void TestProduct()
{
"~/Product/750".Route().ShouldMapTo<ProductController>(x => x.GetById(750));
}
[Test]
public void TestProductListValidYear()
{
"~/ProductList/2009".Route().ShouldMapTo<ProductController>(x => x.List(2009));
}
[Test]
public void TestProductListInvalidYear()
{
Assert.AreNotEqual("~/ProductList/1800".Route().Values["controller"], "Product");
}
[Test]
public void TestIgnoreAxd()
{
"~/someroutetoigonre.axd".ShouldBeIgnored();
}
* This source code was highlighted with Source Code Highlighter.
Здесь представлено четыре теста:
- TestProduct – предназначен для тестирования маршрута Product;
- TestProductListValidYear – тест для тестирования маршрута с ограничением при правильно заданном параметре year;
- TestProductListInvalidYear — тест для тестирования маршрута с ограничением при неправильно заданном параметре year;
- TestIgnoreAxd – тест для тестирования маршрута игнорирования запросов к axd-ресурсам.
И последнее на что стоит обратить внимание – это то, как легко создается тест для проверки маршрутов игнорирования. Метод расширения ShouldBeIgnored позволяет задать тест для таких маршрутов. В нашем тесте TestIgnoreAxd мы пытаемся представить ситуацию с обращением к некоему axd-ресурсу, которое, согласно заданным маршрутам должно игнорироваться.
Скомпилируем и запустим тесты в NUnit:
Все тесты пройдены. Работа сделана.
Заключение
В этой статье я рассмотрел простейшие варианты тестов для модульного тестирования маршрутов в ASP.NET MVC. Инструменты, которые представлены в библиотеке MvcContrib позволяют очень просто создавать такие тесты и, безусловно, облегчают жизнь разработчику.
Для своих проектов, вероятно, вы захотите создать более подробные модульные тесты работы механизма маршрутизации. В этом вам поможет MvcContrib. Программируйте с удовольствием!