ASP.NET MVC:使用UrlHelper的unit testing控制器

我的控制器操作之一,即在Ajax请求中调用的一个操作,正在向客户端返回一个URL,以便它可以执行redirect。 我正在使用Url.RouteUrl(..)并在我的unit testing过程中失败,因为Controller.Url参数未预先填充。

我尝试了很多东西,其中包括尝试存根UrlHelper (失败),手动创buildUrlHelper与具有存根的HttpContextBase (在RouteCollection.GetUrlWithApplicationPath调用失败)的RouteCollection.GetUrlWithApplicationPath

我search了Google,但在这个主题上几乎找不到任何东西。 我在我的控制器操作中使用Url.RouteUrl来做一些令人难以置信的蠢事? 有更容易的方法吗?

更糟的是,我希望能够在我的unit testing中testing返回的URL – 事实上,我只是有兴趣知道它正在redirect到正确的路线,但因为我返回一个URL而不是路线,我想控制解决的URL(例如通过使用一个存根的RouteCollection ) – 但我很乐意让我的testing通过开始。

这是我的一个testing(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); 

eu-ge-ne的修改实现。 这个基于应用程序中定义的路由返回一个生成的链接。 欧格尼的例子总是返回一个固定的答案。 下面的方法将允许您testing正确的操作/控制器和路由信息正在传递到UrlHelper – 如果您正在testing对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); 

如果你想模拟HttpContextBase类,这个post可能会有用。

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

build立@ eu-ge-ne的答案帮了我很大的忙:

我有一个ActionResult做了一个redirect,以及一个带有FormCollection参数的UpdateModel调用。 对于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()); 

要testingredirect的URL是否正确,您可以执行以下操作:

 RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult; Assert.AreEqual("/Expected/URL", result.Url); 

http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html讨论了如何用unit testing覆盖所有的图层。它使用Rhino和MVC.Contrib来进行控制器的testing。 谷歌的源代码可能是一个很大的帮助。