寻找单元测试方向的控制器扩展,以呈现局部视图

时间:2012-01-14 00:33:46

标签: asp.net-mvc asp.net-mvc-3 unit-testing nunit mvccontrib-testhelper

正如标题所说,我正在寻找如何正确测试控制器扩展的方向。扩展呈现部分视图,而这又是我在JSONResult中使用的:

 public static string RenderPartialViewToString(this Controller controller, string viewName = null, object model = null)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
            }

            controller.ViewData.Model = model;

            using (StringWriter sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);
                return sw.GetStringBuilder().ToString();
            }
        }

使用示例:

public JsonResult Foo()
{
    var model = _repository.getSomeData();

    return Json(new { html = this.RenderPartialViewToString("Index", model) }, JsonRequestBehavior.AllowGet);
}

我正在使用NUnit& MvcContrib test helper,但是当设置一个使用此扩展的控制器时,我遇到了NRE。我假设控制器上下文没有正确设置?

最终,测试正在ViewEngines.Engines.FindPartialView上进行。以下是失败测试的一部分:

var routeData = new RouteData();
routeData.Values.Add("controller", "someName");
routeData.Values.Add("action", "someAction");

var builder = new TestControllerBuilder();
var controller = new ListingController(repository.Object);
builder.RouteData = routeData;
builder.InitializeController(controller);

var result = controller.Foo();

1 个答案:

答案 0 :(得分:22)

您必须将模拟的视图引擎添加到ViewEngines.Engines集合,以便您可以模拟FindPartialView调用。以下是Rhino Mocks的一个例子:

var view = MockRepository.GenerateStub<IView>();
var engine = MockRepository.GenerateStub<IViewEngine>();
var viewEngineResult = new ViewEngineResult(view, engine);
engine
    .Stub(x => x.FindPartialView(null, null, false))
    .IgnoreArguments()
    .Return(viewEngineResult);
ViewEngines.Engines.Add(engine);

然后你可以断言调用view.Render方法,拦截它的参数并将一些模拟数据写入这个编写器,最后断言你的控制器动作返回了这个模拟的字符串。