170

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

我尝试了很多东西,其中包括尝试存根UrlHelper(失败),手动创建一个UrlHelper带有RequestContext存根的 a (调用失败)HttpContextBaseRouteCollection.GetUrlWithApplicationPath

我搜索了谷歌,但几乎没有找到关于这个主题的任何内容。我Url.RouteUrl在控制器动作中使用了一些非常愚蠢的东西吗?有没有更简单的方法?

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

4

5 回答 5

202

这是我针对类似情况的测试之一(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);
于 2009-03-23T21:18:03.860 回答
37

来自 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);
于 2011-12-06T23:52:55.353 回答
12

如果您想模拟 HttpContextBase 类,这篇文章可能很有用。

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

于 2009-04-28T20:35:28.827 回答
2

以@eu-ge-ne 的答案为基础,这对我有很大帮助:

我有一个执行重定向的 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());

要测试重定向的 URL 是否正确,您可以执行以下操作:

RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);
于 2009-11-10T23:04:15.787 回答
1

http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html讨论了如何使用单元测试覆盖所有层。它使用 Rhino 和 MVC.Contrib 进行控制器测试。google 上的源代码可能会有很大帮助。

于 2010-11-27T11:37:51.963 回答