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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:26:20  来源:igfitidea点击:

ASP.NET MVC: Unit testing controllers that use UrlHelper

asp.net-mvcunit-testingurlhelper

提问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 上的源代码可能会有很大帮助。