私は、JsonResult を返すコントローラーの 1 つでメソッドを単体テストしようとしていました。驚いたことに、次のコードは機能しませんでした。
[HttpPost]
public JsonResult Test() {
return Json(new {Id = 123});
}
これは私がテストする方法です (テスト コードは別のアセンブリに存在することにも注意してください)。
// Act
dynamic jsonResult = testController.Test().Data;
// Assert
Assert.AreEqual(123, jsonResult.Id);
例外がAssert
スローされます:
「オブジェクト」には「ID」の定義が含まれていません
私はその後、次の方法でこの問題を解決しました。
[HttpPost]
public JsonResult Test() {
dynamic data = new ExpandoObject();
data.Id = 123;
return Json(data);
}
最初のものがなぜ機能しないのかを理解しようとしています。また、匿名型以外であれば基本的にすべて機能しているようです。
ベストアンサー1
明確に言うと、あなたが遭遇している具体的な問題は、C# dynamic が非パブリック メンバーでは機能しないということです。これは設計によるもので、おそらくそのようなことを避けるためのものでしょう。LukLed が述べたように、匿名型は同じアセンブリ内でのみパブリックであるため (または、より正確には、匿名型はinternal
ではなく とマークされるだけなのでpublic
)、この障壁にぶつかっています。
おそらく最もクリーンな解決策は、 を使用することですInternalsVisibleTo
。これにより、非パブリック メンバーにアクセスできる別のアセンブリに名前を付けることができます。これをテストに使用することが、これが存在する主な理由の 1 つです。例では、プライマリ プロジェクトの AssemblyInfo.cs に次の行を配置します。
[assembly: InternalsVisibleTo("AssemblyNameOfYourTestProject")]
それを実行すると、エラーは解消されます (自分で試してみました)。
あるいは、ブルートフォースリフレクションを使用することもできます。
Assert.AreEqual(123, jsonResult.GetType().GetProperty("Id").GetValue(jsonResult, null));