13

正如标题所说,我正在寻找如何正确测试控制器扩展的方向。该扩展呈现一个局部视图,而我又在 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 测试助手,但是在设置使用此扩展的控制器时,我遇到了 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();
4

1 回答 1

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);

Then you could assert that the view.Render method was called, intercept its arguments and write some mocked data to this writer and finally assert that your controller action returned this mocked string.

于 2012-01-14T09:00:41.140 回答