ASP.NET MVC: контроллеры модульного тестирования, использующие UrlHelper - PullRequest
168 голосов
/ 23 марта 2009

Одно из моих действий контроллеров, которое вызывается в Ajax-запросе, возвращает URL-адрес клиентской стороне, чтобы он мог выполнить перенаправление. Я использую Url.RouteUrl(..), и во время моих модульных тестов это не удается, поскольку параметр Controller.Url не заполнен заранее.

Я много чего пробовал, в том числе пытался заглушить UrlHelper (что не удалось), вручную создав UrlHelper с RequestContext, у которого заглушка HttpContextBase (не удалось при вызове RouteCollection.GetUrlWithApplicationPath ).

Я искал в Google, но практически ничего не нашел по этому вопросу. Я делаю что-то невероятно глупое, используя Url.RouteUrl в своем действии контроллера? Есть ли более простой способ?

Чтобы сделать это еще хуже, я хотел бы иметь возможность проверить возвращенный URL-адрес в моем модульном тесте - на самом деле меня интересует только то, что он перенаправляет на правильный маршрут, но так как я возвращаю URL-адрес вместо маршрута я хотел бы управлять разрешенным URL-адресом (например, с помощью пометки RouteCollection), но я буду рад начать тестирование с начала.

Ответы [ 5 ]

200 голосов
/ 24 марта 2009

Вот один из моих тестов (xUnit + Moq) только для аналогичного случая (с использованием Url.RouteUrl в контроллере)

Надеюсь, это поможет:

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);

var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");

var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var controller = new LinkbackController(dbF.Object);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
36 голосов
/ 07 декабря 2011

Модифицированная реализация от eu-ge-ne. Этот возвращает сгенерированную ссылку на основе маршрутов, определенных в приложении. Пример eu-ge-ne всегда возвращал фиксированный ответ. Приведенный ниже подход позволит вам проверить, что правильное действие / контроллер и информация о маршруте передаются в UrlHelper - это то, что вам нужно, если вы тестируете вызов UrlHelper.

var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();

context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);

request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new NameValueCollection());

response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);

context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var helper = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);
12 голосов
/ 29 апреля 2009

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

http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx

2 голосов
/ 11 ноября 2009

Построение ответа @ eu-ge-ne, который мне очень помог:

У меня был ActionResult, который выполнял перенаправление, а также имел вызов UpdateModel с параметром FormCollection. Чтобы UpdateModel () работал, мне нужно было добавить это в мой Mocked HttpRequestBase:

FormCollection collection = new FormCollection();
collection["KeyName"] = "KeyValue";

request.Setup(x => x.Form).Returns(collection);
request.Setup(x => x.QueryString).Returns(new NameValueCollection());

Чтобы проверить правильность перенаправленного URL, вы можете сделать следующее:

RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);
1 голос
/ 27 ноября 2010

http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html обсуждается, как покрыть все слои модульными тестами. Используется Rhino и MVC.Contrib для тестирования контроллеров. Исходный код на Google может быть очень полезным.

...