单元测试ViewEngines.Engines.FindView的正确方法是什么?

时间:2010-07-30 21:55:34

标签: asp.net-mvc asp.net-mvc-2

我最近对我的mvc应用程序进行了一些重构,并意识到返回了很多静态视图。而不是让多个控制器具有仅返回视图的操作结果,我决定创建一个控制器,如果它们存在则返回静态视图,如果视图不存在则抛出404错误。

public ActionResult Index(string name)
{
    ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);

    if (result.View == null)
        ThrowNotFound("Page does not exists.");

    return View(name);
}

我的问题是单元测试的正确方法是什么?我尝试了下面的代码,但我得到的错误是“RouteData必须包含一个名为'controller'且带有非空字符串值的项目。”

[Theory]
[InlineData("ContactUs")]
public void Index_should_return_view_if_view_exists(string name)
{
    controller = new ContentController();
    httpContext = controller.MockHttpContext("/", "~/Content/Index", "GET"); ;

    var result = (ViewResult)controller.Index(name);

    Assert.NotNull(result.View);
}

我的目的是让单元测试结束并获取真实视图。然后我开始怀疑是否应该使用SetupGet为FindView模拟ViewEngines并创建两个测试,其中第二个测试如果视图为null则抛出未找到的异常。

测试此功能的正确方法是什么?任何指针,示例代码或博客文章都会有所帮助。

由于

1 个答案:

答案 0 :(得分:4)

您应该创建一个模拟的视图引擎并将其放入集合中:

[Theory]
[InlineData("ContactUs")]
public void Index_should_return_view_if_view_exists(string name)
{
    var mockViewEngine = MockRepository.GenerateStub<IViewEngine>();
    // Depending on what result you expect you could set the searched locations
    // and the view if you want it to be found
    var result = new ViewEngineResult(new [] { "location1", "location2" });
    // Stub the FindView method
    mockViewEngine
        .Stub(x => x.FindView(null, null, null, false))
        .IgnoreArguments()
        .Return(result);
    // Use the mocked view engine instead of WebForms
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(mockViewEngine);

    controller = new ContentController();

    var actual = (ViewResult)controller.Index(name);

    Assert.NotNull(actual.View);
}