ASP.NET MVC:使用 UrlHelper 的单元测试控制器

发布于 2024-07-15 08:05:13 字数 620 浏览 10 评论 0原文

我的控制器操作之一(在 Ajax 请求中调用的操作)正在向客户端返回一个 URL,以便它可以执行重定向。 我正在使用 Url.RouteUrl(..) ,在单元测试期间,由于 Controller.Url 参数未预先填充,因此失败。

我尝试了很多方法,其中包括尝试存根 UrlHelper (失败),手动创建一个 UrlHelper 以及带有存根的 RequestContext HttpContextBase(在 RouteCollection.GetUrlWithApplicationPath 调用上失败)。

我在谷歌上搜索过,但几乎没有发现任何关于这个主题的信息。 我是否在控制器操作中使用 Url.RouteUrl 做了一些极其愚蠢的事情? 有更容易的方法吗?

更糟糕的是,我希望能够在单元测试中测试返回的 URL - 事实上我只想知道它重定向到正确的路由,但因为我返回的是 URL 而不是路线,我想控制解析的 URL(例如,通过使用存根的 RouteCollection) - 但我很高兴让我的测试开始通过。

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.Url parameter is not pre-filled.

I tried a lot of things, among others attempting to stub UrlHelper (which failed), manually creating a UrlHelper with a RequestContext that has a stubbed HttpContextBase (which failed on a RouteCollection.GetUrlWithApplicationPath call).

I have searched Google but found virtually nothing on the subject. Am I doing something incredibly stupid using Url.RouteUrl in my Controller action? Is there an easier way?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

多像笑话 2024-07-22 08:05:13

这是我针对类似情况的测试之一(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);

Here is one of my tests (xUnit + Moq) just for similar case (using Url.RouteUrl in controller)

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);
谁把谁当真 2024-07-22 08:05:13

来自 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);

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.

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);
作业与我同在 2024-07-22 08:05:13

构建@eu-ge-ne的答案,这对我有很大帮助:

我有一个执行重定向的 ActionResult 以及带有 FormCollection 参数的 UpdateModel 调用。 为了使 UpdateModel() 正常工作,我必须将其添加到我的模拟 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);

Building off the answer by @eu-ge-ne which helped me a great deal:

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:

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:

RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文