asp.net-mvc ASP.NET MVC:使用 UrlHelper 的单元测试控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/674458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC: Unit testing controllers that use UrlHelper
提问by efdee
One of my controllers actions, one that is being called in an Ajax request, is returning an URL to the client side so it can do a redirection. I'm using Url.RouteUrl(..)and during my unit tests this fails since the Controller.Urlparameter is not pre-filled.
我的控制器操作之一,在 Ajax 请求中被调用,正在向客户端返回一个 URL,以便它可以进行重定向。我正在使用Url.RouteUrl(..)并且在我的单元测试期间失败,因为该Controller.Url参数未预填充。
I tried a lot of things, among others attempting to stub UrlHelper(which failed), manually creating a UrlHelperwith a RequestContextthat has a stubbed HttpContextBase(which failed on a RouteCollection.GetUrlWithApplicationPathcall).
我尝试了很多事情,其中包括尝试存根UrlHelper(失败),手动创建一个UrlHelper带有RequestContext存根的HttpContextBase(在RouteCollection.GetUrlWithApplicationPath调用时失败)。
I have searched Google but found virtually nothing on the subject. Am I doing something incredibly stupid using Url.RouteUrlin my Controller action? Is there an easier way?
我已经搜索过谷歌,但几乎没有发现关于这个主题的任何内容。我Url.RouteUrl在我的控制器操作中使用了一些非常愚蠢的东西吗?有更容易的方法吗?
To make it even worse, I'd like to be able to test the returned URL in my unit test - in fact I'm only interested in knowing it's redirecting to the right route, but since I'm returning an URL instead of a route, I would like to control the URL that is resolved (eg. by using a stubbed RouteCollection) - but I'll be happy to get my test passing to begin with.
更糟糕的是,我希望能够在我的单元测试中测试返回的 URL - 事实上我只对知道它重定向到正确的路由感兴趣,但是因为我返回的是一个 URL 而不是一个路由,我想控制解析的 URL(例如,通过使用 stubbed RouteCollection) - 但我很高兴让我的测试通过。
回答by eu-ge-ne
Here is one of my tests (xUnit + Moq) just for similar case (using Url.RouteUrl in controller)
这是我的测试之一(xUnit + Moq),仅用于类似情况(在控制器中使用 Url.RouteUrl)
Hope this helps:
希望这可以帮助:
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);
回答by Steven Pena
A modified implementation from eu-ge-ne. This one returns a generated link based on the routes defined in the application. eu-ge-ne's example always returned a fixed response. The approach below will allow you to test that the correct action/controller and route information is being passed into the UrlHelper - which is what you want if you are testing call to the UrlHelper.
来自 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);
回答by Gerardo Contijoch
This post may be useful if you want to mock HttpContextBase class.
如果您想模拟 HttpContextBase 类,这篇文章可能很有用。
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
回答by jebcrum
Building off the answer by @eu-ge-ne which helped me a great deal:
建立@eu-ge-ne 的答案,这对我有很大帮助:
I had an ActionResult that did a redirect as well as had an UpdateModel call with a FormCollection parameter. For the UpdateModel() to work I had to add this to my Mocked HttpRequestBase:
我有一个 ActionResult 进行了重定向,并且有一个带有 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());
To test that the redirected URL was correct, you can do the following:
要测试重定向的 URL 是否正确,您可以执行以下操作:
RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);
回答by hurbata
http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.htmldiscusses how to cover all the layers with unit tests.It uses Rhino and MVC.Contrib for the controllers testing. The source code on google may be of a great help.
http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html讨论了如何用单元测试覆盖所有层。它使用 Rhino 和 MVC.Contrib 进行控制器测试。google 上的源代码可能会有很大帮助。

