【问题标题】:How to Unit Test a custom ModelBinder using Moq?如何使用 Moq 对自定义 ModelBinder 进行单元测试?
【发布时间】:2010-11-08 00:51:33
【问题描述】:

我在编写一些单元测试来测试我创建的自定义 ModelBinder 时遇到了一些困难。我尝试进行单元测试的 ModelBinder 是我发布的 here 的 JsonDictionaryModelBinder。

我遇到的问题是使用 Moq 进行 Mocking all 设置。由于 HttpContextBase 未正确模拟,我不断收到 Null 异常。我想。

有人可以帮我弄清楚我做错了什么吗?

这是我正在尝试编写但不起作用的单元测试示例:

[TestMethod()]
public void BindModelTest()
{
    JsonDictionaryModelBinder target = new JsonDictionaryModelBinder();

    NameValueCollection nameValueCollection = new NameValueCollection() {
        {"First", "1"},
        {"Second", "2"},
        {"Name", "Chris"},
        {"jsonValues", "{id: 200, name: 'Chris'}"}
    };

    HttpContextBase httpContext = MockHelper.FakeHttpContext(HttpVerbs.Post, nameValueCollection);

    ControllerContext controllerContext =
        new ControllerContext(new RequestContext(httpContext, new RouteData()), new Mock<Controller>().Object);


    Predicate<string> predicate = propertyName => (propertyName == "jsonValues");
    ModelBindingContext bindingContext = new ModelBindingContext()
    {
        Model = null,
        ModelType = typeof(JsonDictionary),
        ModelState = new ModelStateDictionary(),
        PropertyFilter = predicate,
        ValueProvider = new Dictionary<string, ValueProviderResult>() { { "foo", null } }
    };

    //object expected = null; // TODO: Initialize to an appropriate value
    var actual = target.BindModel(controllerContext, bindingContext) as JsonDictionary;

    Assert.IsNotNull(actual);

    Assert.AreEqual("Chris", actual["name"]);
    //Assert.AreEqual(expected, actual);
    Assert.Inconclusive("Verify the correctness of this test method.");
}

这是上面使用的“FakeHttpContext”方法:

public static class MockHelper
{
    public static HttpContextBase FakeHttpContext(HttpVerbs verbs, NameValueCollection nameValueCollection)
    {
        var httpContext = new Mock<HttpContextBase>();

        var request = new Mock<HttpRequestBase>();
        request.Setup(c => c.Form).Returns(nameValueCollection);
        request.Setup(c => c.QueryString).Returns(nameValueCollection);

        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();
        httpContext.Setup(c => c.Request).Returns(request.Object);

        var u = verbs.ToString().ToUpper();
        httpContext.Setup(c => c.Request.RequestType).Returns(
            verbs.ToString().ToUpper()
        );

        httpContext.Setup(c => c.Response).Returns(response.Object);
        httpContext.Setup(c => c.Server).Returns(server.Object);
        httpContext.Setup(c => c.User.Identity.Name).Returns("testclient");
        return httpContext.Object;
    }
}

【问题讨论】:

    标签: asp.net-mvc unit-testing moq modelbinders


    【解决方案1】:

    罪魁祸首是这一行:

    httpContext.Setup(c => c.Request.RequestType).Returns(
                    verbs.ToString().ToUpper()
                );
    

    从技术上讲,这是 Request 对象上的第二个 Setup,它正在清除原来的 Setup,即使您要在对象层次结构中“过去”它。我不确定这是最小起订量中的错误还是期望的行为,我之前也遇到过这个问题,还没有抽出时间来检查它。

    您可以通过将该行移至上面设置请求的位置并直接设置它来解决它,而不是通过 httpContext.所以,

    request.Setup(c => c.RequestType).Returns(verbs.ToString().ToUpper());
    

    我还注意到您声明的“var u”没有被使用;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      • 2021-10-24
      • 2011-12-24
      • 2012-06-01
      • 2014-12-30
      • 2018-05-27
      相关资源
      最近更新 更多