我的一个控制器操作,一个在Ajax请求中调用的操作,正在向客户端返回一个URL,以便它可以进行重定向。我正在使用Url.RouteUrl(..)
并且在我的单元测试期间由于Controller.Url
参数未预填充而失败。
我尝试了很多其他内容,其中包括尝试存根UrlHelper
(失败),手动创建UrlHelper
,RequestContext
有一个存根HttpContextBase
({1}}在RouteCollection.GetUrlWithApplicationPath
电话中失败了。
我搜索了谷歌,但几乎没有发现这个问题。我在Controller操作中使用Url.RouteUrl
做了一些非常愚蠢的事情吗?有更简单的方法吗?
更糟糕的是,我希望能够在我的单元测试中测试返回的URL - 实际上我只是想知道它重定向到正确的路由,但是因为我正在返回一个URL而不是路线,我想控制已解决的URL(例如,通过使用存根RouteCollection
) - 但我很乐意让我的测试通过开始。
答案 0 :(得分:200)
这是我的一个测试(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);
答案 1 :(得分:36)
来自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);
答案 2 :(得分:12)
如果你想模拟HttpContextBase类,这篇文章可能很有用。
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
答案 3 :(得分: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());
要测试重定向的网址是否正确,您可以执行以下操作:
RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);
答案 4 :(得分:1)
http://kbochevski.blogspot.com/2010/06/unit-testing-mvcnet.html讨论如何使用单元测试覆盖所有层。它使用Rhino和MVC.Contrib进行控制器测试。谷歌上的源代码可能会有很大的帮助。