ASP.NET MVC: Контроллеры модулей тестирования, использующие UrlHelper
Один из моих действий с контроллерами, вызываемый в запросе Ajax, возвращает URL-адрес на стороне клиента, чтобы он мог перенаправлять. Я использую Url.RouteUrl(..)
, и во время моих модульных тестов это терпит неудачу, поскольку параметр Controller.Url
не предварительно заполнен.
Я пробовал много вещей, среди прочего, пытаясь заглушить UrlHelper
(который не удался), вручную создав UrlHelper
с RequestContext
, который имеет окутанный HttpContextBase
(который потерпел неудачу при вызове RouteCollection.GetUrlWithApplicationPath
).
Я искал Google, но практически ничего не нашел по этому вопросу. Я делаю что-то невероятно глупо, используя Url.RouteUrl
в моем действии Controller? Есть ли более простой способ?
Чтобы сделать это еще хуже, я бы хотел проверить тестовый URL-адрес в моем unit test - на самом деле мне просто интересно узнать, что он перенаправляется на правильный маршрут, но поскольку я возвращаю URL вместо маршрута, я хотел бы контролировать URL-адрес, который разрешен (например, с помощью окутанного RouteCollection
), но я с удовольствием пройду свою тестовую передачу.
Ответы
Ответ 1
Вот один из моих тестов (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);
Ответ 2
Измененная реализация от 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);
Ответ 3
Эта запись может быть полезна, если вы хотите высмеять класс HttpContextBase.
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
Ответ 4
Построение ответа от @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);
Ответ 5
http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html обсуждает, как покрыть все слои модульными тестами. Он использует Rhino и MVC.Contrib для тестирования контроллеров. Исходный код в google может оказать большую помощь.