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 が要求本文で呼び出されることに気付いたのは正しいことです。現在、2 つの奇妙なことが起こっています。

  • 最初のテストに渡す型は FilterItemDTO です。しかし、結果は TestClass になると思いますか? フォーマッタに渡す型は、逆シリアル化されていると予想される型です。代わりに TestClass を ReadFromStreamAsync に渡すつもりでしたか?
  • TestClass にはメンバー Type と Value があるため、Json.NET は、"type" と "value" ではなく、メンバー "Type" と "Value" を JSON に期待します。大文字と小文字は重要です。しかし、この行でキャメル ケーシングを取得する簡単な方法があります。コードの:

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