0

AJAX呼び出しが成功した場合、単純なオブジェクトを返したいSuccess = true

public ActionResult Foo(int id)
{
    // ...
    return Json(new {Success=true});
}

これは正常に動作し、JavaScript が受け取るオブジェクトは次のようになります

{ Success : true }  

ただし、返されるオブジェクトは匿名型であるため、テストで次のことを行うことはできません (次のようなことはできません)。

var result = (JsonResult)controller.AddNote(id, message);
dynamic data = result.Data;

// Assert
Assert.That(data.Success, Is.EqualTo(true));

そのため、テストを希望どおりに機能させる ExpandoObject を返そうとしましたが、AJAX 応答で返された JSON は、この質問で詳しく説明されているように混乱しています。

[{"Key":"Success","Value":true}]

簡単だと思われることを達成するためのシンプルでクリーンな方法はありますか、それともリンクされた質問のようにカスタムシリアライゼーションを実装する唯一の方法ですか?

4

2 に答える 2

1
  1. dynamicコントローラ アセンブリに[assembly: InternalsVisibleTo("TestsProject")]. 匿名型用に生成されたクラスは内部型であり、ランタイム バインディングは内部型では機能しないためです。この記事では、これに関する詳細情報を見つけることができます。
  2. このアプローチが気に入らない場合は、単純な古いリフレクションにフォールバックできます (いくつかのヘルパー メソッドの背後に隠されています)。

    [TestMethod]
    public void AddNote1()
    {
        ...
        var result = ((JsonResult)controller.AddNote(id, message));
        var data = result.Data;
    
        // Assert
        Assert.AreEqual(Get<bool>(data, "Success"), true);
     }
    
     private T Get<T>(object instance, string propertyName)
     {
         return (T) instance.GetType().GetProperty(propertyName).GetValue(instance, null);
     }
    
  3. 匿名クラスの代わりに名前付きクラスを使用します。

  4. あなたが述べたように、ある種のシリアル化の回避策を使用する必要があります。

于 2011-11-10T19:04:16.837 に答える
0

あなたができることは次のとおりです。

var js = new JavaScriptSerializer();
var response = new { id = 0, Status = false };
dynamic object = js.Deserialize(new StringReader(JSONText), response.GetType());

Assert.IsTrue(object.Success)

これが行うことは次のとおりです。

  1. JavaScriptSerializer を作成します。
  2. json と同じレイアウトで新しい匿名オブジェクトを作成して、シリアライザーがオブジェクトの外観を認識できるようにします。
  3. json を新しい動的オブジェクトに逆シリアル化します。

これの欠点は、json オブジェクトに IntelliSense がないため、スペル ミスがコンパイラによって検出されないことです。

注: ここのコードは stackoverflow で記述したため、マイナーなバグがある可能性があります。私はそれをテストしませんでしたが、動作するはずです:P

于 2011-11-10T18:30:37.683 に答える