为剃刀助手测试单元纠正Http / Controller上下文的模拟

时间:2016-01-18 13:49:44

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

我有一个问题,试图创建一个单元测试来测试自定义剃刀助手(使用kendo网格剃刀助手)。 问题来自kendo网格助手,它试图访问以下属性:HtmlHelper.ViewContext.Controller.ValueProvider(并抛出NullReferenceException。此异常来自对控制器上下文的ValueProvider属性的访问)。

我总结说我的"模拟" http /控制器上下文未正确初始化。我尝试在互联网上找到的几种解决方案来模拟上下文,但我仍然有问题)。

这是我目前的单元测试代码:

ModelMock model = ...
ViewDataDictionary vd = new ViewDataDictionary(model);

var htmlHelper = CreateHtmlHelper<ModelMock>(vd);
string htmlResult = htmlHelper.PopinGrid(m => m.JsonList).ToHtmlString(); // This is the call of my helper.

... (asserts)

我帮助你进行上下文模拟(他们使用其他简单的剃刀助手单元测试):

public static HtmlHelper<T> CreateHtmlHelper<T>(ViewDataDictionary viewDataDictionary)
    where T : new()
{
    Mock<ControllerBase> controller = new Mock<ControllerBase>();

    Mock<ControllerContext> controllerContext = new Mock<ControllerContext>(
        new Mock<HttpContextBase>().Object,
        new RouteData(),
        controller.Object);

    Mock<ViewContext> viewContext = new Mock<ViewContext>(
        controllerContext.Object,
        new Mock<IView>().Object,
        viewDataDictionary,
        new TempDataDictionary(),
        new StringWriter(CultureInfo.InvariantCulture));

    Mock<IViewDataContainer> mockViewDataContainer = new Mock<IViewDataContainer>();

    bool unobtrusiveJavascriptEnabled = false;
    bool clientValidationEnabled = true;
    viewContext.SetupGet(c => c.UnobtrusiveJavaScriptEnabled).Returns(unobtrusiveJavascriptEnabled);
    viewContext.SetupGet(c => c.FormContext).Returns(new FormContext { FormId = "myForm" });
    viewContext.SetupGet(c => c.ClientValidationEnabled).Returns(clientValidationEnabled);
    viewContext.SetupGet(c => c.ViewData).Returns(viewDataDictionary);
    // I add the following line because the "Controller" property of the viewContext was null (strange, given that I initialize the view context with the controller context).
    viewContext.SetupGet(c => c.Controller).Returns(controller.Object); 

    mockViewDataContainer.Setup(v => v.ViewData).Returns(viewDataDictionary);
    HttpContext.Current = FakeHttpContext();
    return new HtmlHelper<T>(viewContext.Object, mockViewDataContainer.Object);
}

public static HttpContext FakeHttpContext()
{
    HttpRequest httpRequest = new HttpRequest(string.Empty, "http://mockurl/", string.Empty);
    StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
    HttpResponse httpResponse = new HttpResponse(stringWriter);
    HttpContext httpContext = new HttpContext(httpRequest, httpResponse);

    HttpSessionStateContainer sessionContainer = new HttpSessionStateContainer(
        "id",
        new SessionStateItemCollection(),
        new HttpStaticObjectsCollection(),
        10,
        true,
        HttpCookieMode.AutoDetect,
        SessionStateMode.InProc,
        false);

    httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance,
            null,
            CallingConventions.Standard,
            new[] { typeof(HttpSessionStateContainer) },
            null)
        .Invoke(new object[] { sessionContainer });

    return httpContext;
}

有人知道模拟完整的http /控制器上下文的好方法吗?

谢谢!

0 个答案:

没有答案