首页 文章

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

提问于
浏览
167

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

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

我搜索了谷歌,但几乎没有发现这个问题 . 我在Controller操作中使用 Url.RouteUrl 做了一些非常愚蠢的事情吗?有没有更简单的方法?

更糟糕的是,我只是想知道's redirecting to the right route, but since I' m返回一个URL而不是一个路由,我想控制解析的URL(例如通过使用存根 RouteCollection ) - 但我会很高兴让我的测试通过开始 .

5 回答

  • 34

    这是我的一个测试(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

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

    如果你想模拟HttpContextBase类,这篇文章可能会有用 .

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

  • 2

    Build @ 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);
    
  • 198

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

相关问题