5

目标:测试给定的 url 返回给定的控制器函数。

在这个过程中,我闯入了路由系统,我无法弄清楚如何测试路由(或者,就此而言,找到与路由对应的控制器:-/)。

示例代码,不起作用:

[Test]       
public void kick_the_tires()
{
   var rc = new RouteCollection();

   Infrastructure.RouteRegistry.RegisterRoutes(rc);

   // get the route corresponding to name.
   var got = rc["name"];

   var expected = //What? foo is an internal type that can't be instantiated.

   Assert.AreEqual(foo, frob);
}

编辑:使用来自 Simon 的链接博客文章作为存根类。

[TestCase("/", "~/", "Home", "Index")]
[TestCase("/", "api/command", "Other", "command")]
internal void stub_mocker(string apppath, string route, string expected_controller,\
  string expected_action)
{
  var rc = new RouteCollection();
  Infrastructure.RouteRegistry.RegisterRoutes(rc);

  var httpmock = new StubHttpContextForRouting(
      appPath: apppath,
      requestUrl: route);

  // this always returns null for everything but the Index case.
  var routeData = rc.GetRouteData(httpmock);

  var controller = routeData.Values["controller"];
  var action = routeData.Values["action"];
  Assert.AreEqual(expected_controller, controller);
  Assert.AreEqual(expected_action, action);
}
4

2 回答 2

5

您现在正在测试的只是路由是否被添加到集合中,通过路由名称访问它,而不是如果预期的路由将返回给定的虚拟路径。您需要使用 HttpContext 获取 RouteCollection 返回的路由数据。

最好的方法是对 HttpContext(或 HttpContextBase)使用模拟或存根,并调用 RouteCollection 的 GetRouteData(HttpContextBase) 方法并检查路由数据。

Brad Wilson 的博客中有一个很好的例子:http: //bradwilson.typepad.com/blog/2010/07/testing-routing-and-url-generation-in-aspnet-mvc.html

编辑:您无法从 RouteData 本身获取控制器实例。但是,RouteData 应该为您提供足够的信息来了解将实例化哪个控制器。例如,如果你有一个MyProject.Controllers.HomeController带有 action的控制器Home,这应该在你的测试中成立(使用 xUnit 和 Moq):

// Prepare
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.SetupGet(c => c.Request).Returns(request.Object);
context.SetupGet(c => c.Response).Returns(response.Object);
context.SetupGet(c => c.Session).Returns(session.Object);
context.SetupGet(c => c.Server).Returns(server.Object);
request.SetupGet(r => r.HttpMethod).Returns("GET");
request.SetupGet(r => r.PathInfo).Returns(String.Empty);
request.SetupGet(r => r.AppRelativeCurrentExecutionFilePath).Returns("~/Home");


var expectedHandler = typeof (HomeController).GetMethod("Index", Type.EmptyTypes);

var data = RouteTable.Routes.GetRouteData(context.Object);

Assert.NotNull(data);

var handler = (MethodInfo) data.DataTokens["actionMethod"];
Assert.Equal(expectedHandler, handler);
于 2013-06-25T00:37:37.050 回答
1

我对MVCContrib 的 Testhelper有过很好的体验

看看这个testhelper的测试。

节省了很多关于存根HttpContext等的麻烦。

另外,如果您使用的是 MVC4,请查看这个 Nuget 包,它是 MVC4 的一个分支。

于 2013-06-26T02:01:36.153 回答