通过以编程方式执行Controller来捕获Action的结果(使用RouteData)

时间:2013-09-30 09:08:06

标签: asp.net-mvc

我从Darin Dimitrov找到了以下答案 - In ASP MVC3, how can execute a controller and action using a uri?

var routeData = new RouteData();
// controller and action are compulsory
routeData.Values["action"] = "index";
routeData.Values["controller"] = "foo";
// some additional route parameter
routeData.Values["foo"] = "bar";
IController fooController = new FooController();
var rc = new RequestContext(new HttpContextWrapper(HttpContext), routeData);
fooController.Execute(rc);

唯一的问题是我喜欢捕获此Action返回的ViewResult(将其呈现为字符串),但IController.Execute返回void

我怀疑我可以在ControllerContext的属性中找到Result,但我找不到类似的东西。有没有人知道如何做到这一点?

1 个答案:

答案 0 :(得分:0)

根据我的理解,您想要做的是实际呈现视图,获取HTML结果并对其进行断言。

这实际上测试的是几乎不推荐的视图,而且大多数实践都是如此。

但是,你可以想出一些解决方案。呈现的(简化和有点凌乱)使用RazorEngine渲染视图。由于您无法从测试项目访问.cshtml(视图文件),因此您需要以凌乱的方式访问其内容。

将RazorEngine NuGet软件包安装到您的测试项目中,并尝试以下几行:

    [Fact]
    public void Test()
    {
        var x = new HomeController();  // instantiate controller
        var viewResult = (ViewResult)x.Index(); // run the action and obtain its ViewResult
        var view = string.IsNullOrWhiteSpace(viewResult.ViewName) ? "Index" : viewResult.ViewName;     // get the resulted view name; if it's null or empty it means it is the same name as the action
        var controllerName = "Home"; // the controller name was known from the beginning

        // actually navigate to the folder containing the views; in this case we're presuming the test project is a sibling to the MVC project, otherwise adjust the path to the view accordingly
        var pathToView = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Replace("file:\\", "");
        pathToView = Path.GetDirectoryName(pathToView);
        pathToView = Path.GetDirectoryName(pathToView);
        pathToView = Path.GetDirectoryName(pathToView);
        pathToView = Path.Combine(pathToView, "WebApplication5\\Views\\" + controllerName + "\\" + view + ".cshtml");

        var html = Razor.Parse(File.ReadAllText(pathToView), viewResult.Model);  // this is the HTML result, assert against it (i.e. search for substrings etc.)
    }