1

编写用于反序列化 Web API 中的 JSON 对象的单元测试的正确方法是什么?

在我的应用程序中,通过查看跟踪信息,我注意到 Web API 试图通过调用 JsonMeadiaTypeFormatter.ReadFromAsync 来反序列化来自请求正文的对象参数。我试图找出问题,所以我写了这些测试。ReadTestItem 失败。另一个示例 ReadInt 通过了,所以看起来我走在正确的轨道上,但我不确定这是否是 Web API 真正在做的事情。

编辑:代码已修复并添加了 FormatterConfig

class TestClass
{
    public string Type { get; set; }
    public string Value { get; set; }
}

[TestClass]
public class FormatterTest
{
    [TestMethod]
    public void ReadTestItem()
    {
        MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection();
        FormatterConfig.RegisterGlobalFormatters(formatters);

        JsonMediaTypeFormatter formatter = formatters[0] as JsonMediaTypeFormatter;
        Stream s = GenerateStreamFromString("{ type: \"Equal\", value: \"1\" }");
        var content = new StreamContent(s);
        var logger = new Mock<IFormatterLogger>().Object;

        var task = formatter.ReadFromStreamAsync(typeof(TestClass), s, content, logger);
        TestClass result = task.Result as TestClass;
        Assert.AreEqual("Equal", result.Type);
        Assert.AreEqual("1", result.Value);
    }

    [TestMethod]
    public void TestReadInt()
    {
        MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection();
        FormatterConfig.RegisterGlobalFormatters(formatters);

        JsonMediaTypeFormatter formatter = formatters[0] as JsonMediaTypeFormatter;
        Stream s = GenerateStreamFromString("2");
        var content = new StreamContent(s);
        var logger = new Mock<IFormatterLogger>().Object;

        var task = formatter.ReadFromStreamAsync(typeof(int), s, content, logger);
        Assert.AreEqual(2, task.Result);
    }

    public Stream GenerateStreamFromString(string s)
    {
        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
}

这是格式化程序配置:

public class FormatterConfig
{
    public static void RegisterGlobalFormatters(MediaTypeFormatterCollection formatters)
    {
        var jsonSerializerSettings = formatters.JsonFormatter.SerializerSettings;
        jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter());

        // serialize every enum as a string
        jsonSerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

        // include null value fields
        jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;

        // use camel case
        jsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // indented formatting
        bool indent;
        Boolean.TryParse(ConfigurationManager.AppSettings["dex.indentjson"], out indent);
        formatters.JsonFormatter.Indent = indent;

        formatters.Remove(formatters.XmlFormatter);
    }
}
4

1 回答 1

0

这种方法对我来说看起来不错。您注意到 ReadFromStreamAsync 在请求正文上被调用是正确的。现在发生了两件奇怪的事情:

  • 您传入第一个测试的类型是 FilterItemDTO。但是你期望结果是一个TestClass?无论您传递给格式化程序的任何类型都是您应该期望反序列化的类型。您是否打算将 TestClass 传递给 ReadFromStreamAsync ?
  • TestClass 有成员 Type 和 Value,因此 Json.NET 将期望 JSON 中的成员“Type”和“Value”,而不是“type”和“value”。大小写很重要。但是有一种简单的方法可以使用这条线获得驼峰大小写代码:

    config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    
于 2013-04-19T23:41:53.847 回答