如何使用moq模拟ControllerContext?模拟ControllerContext时出错

时间:2011-06-09 19:24:17

标签: c# .net asp.net-mvc unit-testing moq

我正在使用MOQ框架并且我有以下单元测试,它失败并出现以下错误消息“对象引用未设置为对象的实例”在下面的代码行

viewCxt.View.Render(viewCxt, writer);  

有人能指出我正确的方向,为什么这不通过测试?

[Test]
public void can_call_PopulateBankTransactionWorkQueueViewInTransactionMetaDataAjaxResponseObject()
{

    var transactionMetaData = new TransactionMetaDataDTO() { TransactionId = "1", FileId = "1", LockboxNumber = "0402020", DepositDate = "04.26.2011", BatchId = "1" };


    var request = new Mock<HttpRequestBase>();
    request.Setup(r => r.HttpMethod).Returns("GET");
    var mockHttpContext = new Mock<HttpContextBase>();
    mockHttpContext.Setup(c => c.Request).Returns(request.Object);

    var controllerContext = new ControllerContext(mockHttpContext.Object, new Mock<RouteData>().Object, new Mock<ControllerBase>().Object); 

    var checkWorkQueueController = new CheckWorkQueueController(
          activeDirectorySecurityManager.Object,  businessObjectAdapter, httpRequestObjectHelper.Object, invoiceRepos.Object,  new HtmlHelpers());

    checkWorkQueueController.ControllerContext = controllerContext;
    Assert.DoesNotThrow(() => checkWorkQueueController.PopulateBatchTreeSelectorViewInTransactionMetaDataAjaxResponseObject(transactionMetaData));
}

internal void PopulateBatchTreeSelectorViewInTransactionMetaDataAjaxResponseObject(TransactionMetaDataDTO transactionMetaDataDTO)
{

    var checkWorkQueueViewModel = new CheckWorkQueueViewModel(securityManager, businessObjectAdapter);
    SetActiveFileAndLockbox(transactionMetaDataDTO, checkWorkQueueViewModel, transactionMetaDataDTO.FileId, transactionMetaDataDTO.LockboxNumber);
    transactionMetaDataDTO.BatchTreeSelectorView = htmlHelpers.RenderViewToString(ApplicationConstants.CheckWorkQueueViewPath + ApplicationConstants.BatchTreeSelectorViewFileName, this, checkWorkQueueViewModel);
}

public string RenderViewToString<T>(string viewPath, ControllerBase controller, T model)
{
        controller.ViewData.Model = model;
        using (var writer = new StringWriter())
        {
            var view = new WebFormView(viewPath);
            var vdd = new ViewDataDictionary<T>(model);
            var viewCxt = new ViewContext(controller.ControllerContext, view, vdd, new TempDataDictionary(), writer);
            viewCxt.View.Render(viewCxt, writer);  //ERROR throwing here
            return writer.ToString();
        }
}

这是StackTrace:

at System.Web.VirtualPath.GetCacheKey()
at System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath(VirtualPath virtualPath, Boolean& keyFromVPP)
at System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound)
at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp)
at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp)
at System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(String virtualPath, Type requiredBaseType)
at System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.CreateInstanceFromVirtualPath(String virtualPath, Type requiredBaseType)
at System.Web.Mvc.WebFormView.Render(ViewContext viewContext, TextWriter writer)

1 个答案:

答案 0 :(得分:1)

调试Mock上实际需要设置的内容的一种好方法是使用MockBehavior.Strict选项创建它。所以,

var mockHttpContext = new Mock<HttpContextBase>();

变为

var mockHttpContext = new Mock<HttpContextBase>(MockBehavior.Strict);

然后,当您需要来自尚未设置的Context的某些内容时,您的测试将因MockException而失败。您可以稍后恢复为“松散”选项。