【问题标题】:How to Unit Test a custom JsonConverter in ASP.NET Web API?如何在 ASP.NET Web API 中对自定义 JsonConverter 进行单元测试?
【发布时间】:2015-12-01 10:16:58
【问题描述】:

我有一个自定义 JsonConverter,它从前端获取本地日期时间字符串,并使用 NodaTime 将其转换为 DateTimeOffset

我替换了 Json.NET 中的默认解析器。

formatter.SerializerSettings = new JsonSerializerSettings
          {
              Formatting = Formatting.Indented,
              ContractResolver = new CustomResolver(),
              ReferenceLoopHandling = ReferenceLoopHandling.Ignore
          };

所以在我的测试中我需要确保我配置了这个。

幕后发生的事情是向我的 API 控制器发出 POST 请求。如果 ViewModel(在 API 操作中使用)包含 DateTimeOffset 属性,则关联的 JSON 日期时间属性将通过转换器。

当转换器被触发时,应用程序首先获得User.Identity

var user = (ClaimsIdentity) Thread.CurrentPrincipal.Identity;

成功后,我们提取 Locality 声明,其中包含 IANA 时区 ID(例如“America/New_York”)。

我们使用它来将本地日期时间转换为相应的 DateTimeOffset。

这是我要测试的。

我有 JSON 对象:

NameValueCollection nameValueCollection = new NameValueCollection() {
            {"dateCreated", "2015-11-30T14:22:00+1:00"},
            {"message", "Some message."},
            {"timelinePostId", "1"},
            {"applicationUser", ""},
            {"thumbs","" }
        };

但我不知道如何执行 --

// Arrange

// Act

// Assert

我找到了这个 MockHelper 类,所以我已经准备好使用它了。

public static HttpContextBase FakeHttpContext(HttpVerbs verbs, NameValueCollection nameValueCollection)
{
    var httpContext = new Mock<HttpContextBase>();
    var user = new ApplicationUser { 
            Id = "abc", 
            TimezoneId = "America/New_York" 
        };

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

    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.Response).Returns(response.Object);
    httpContext.Setup(c => c.Server).Returns(server.Object);
    httpContext.Setup(c => c.User.Identity.GetUserId()).Returns("abc");
    httpContext.Setup(c => c.User.ApplicationUser()).Returns(user);
    return httpContext.Object;
}

所以我有我的 JSON 模拟和我的身份模拟,但我如何让它工作呢?非常感谢任何帮助。

【问题讨论】:

  • 在设计我的 web api 控制器时,这种东西让我抓狂。他们让它在教程中看起来很简单。然后,你做现实世界的东西。你真的最终嘲笑了整个网络管道。真是一团糟!我还有一个特殊的 POCO,我为它设计了一个 JSON 转换,由 GlobalConfiguration 注册.. ugh!!

标签: c# unit-testing asp.net-web-api mocking httprequest


【解决方案1】:

这是一种不需要模拟整个 HttpContext 的方法。

在您的 JsonConverter 类中,将 ReadJson 中的逻辑重构为单独的方法,并传入 Identity 对象:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    return DeserializeDate(reader, objectType, existingValue, serializer, (ClaimsIdentity)Thread.CurrentPrincipal.Identity);
}

public object DeserializeDate(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer, ClaimsIdentity identity)
{
    // do stuff...
}

然后针对 DeserializeDate 编写单元测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2023-02-24
    • 2018-05-27
    • 1970-01-01
    相关资源
    最近更新 更多