RPM*_*984 42 c# asp.net-mvc json unit-testing jsonresult
如果我有这样的控制器:
[HttpPost]
public JsonResult FindStuff(string query)
{
var results = _repo.GetStuff(query);
var jsonResult = results.Select(x => new
{
id = x.Id,
name = x.Foo,
type = x.Bar
}).ToList();
return Json(jsonResult);
}
Run Code Online (Sandbox Code Playgroud)
基本上,我从我的存储库中获取东西,然后将其投影到一个List<T>匿名类型中.
我该如何对其进行单元测试?
System.Web.Mvc.JsonResult有一个叫做的属性Data,但它的类型object,正如我们所期望的那样.
那么这是否意味着如果我想测试JSON对象具有我期望的属性("id","name","type"),我必须使用反射?
编辑:
这是我的测试:
// Arrange.
const string autoCompleteQuery = "soho";
// Act.
var actionResult = _controller.FindLocations(autoCompleteQuery);
// Assert.
Assert.IsNotNull(actionResult, "No ActionResult returned from action method.");
dynamic jsonCollection = actionResult.Data;
foreach (dynamic json in jsonCollection)
{
Assert.IsNotNull(json.id,
"JSON record does not contain \"id\" required property.");
Assert.IsNotNull(json.name,
"JSON record does not contain \"name\" required property.");
Assert.IsNotNull(json.type,
"JSON record does not contain \"type\" required property.");
}
Run Code Online (Sandbox Code Playgroud)
但是我在循环中得到一个运行时错误,说明"对象不包含id的定义".
当我断点时,actionResult.Data被定义为一个List<T>匿名类型,所以我想如果我通过这些枚举,我可以检查属性.在循环内部,对象确实有一个名为"id"的属性 - 所以不确定问题是什么.
Ser*_*eit 53
我知道我对这些人有点迟,但我发现为什么动态解决方案不起作用:
JsonResult返回一个匿名对象,默认情况下,这些对象internal需要对测试项目可见.
打开ASP.NET MVC应用程序项目,并
AssemblyInfo.cs从名为Properties的文件夹中查找.打开AssemblyInfo.cs并将以下行添加到此文件的末尾.
[assembly: InternalsVisibleTo("MyProject.Tests")]
Run Code Online (Sandbox Code Playgroud)
引用自: http ://weblogs.asp.net/gunnarpeipman/archive/2010/07/24/asp-net-mvc-using-dynamic-type-to-test-controller-actions-returning-jsonresult.aspx
我认为将这一个用于记录会很好.奇迹般有效
Mat*_*eer 18
RPM,你看起来是正确的.我还有很多东西需要学习,dynamic而且我也无法让Marc的方法得以实现.所以我以前是这样做的.你会发现它很有用.我刚写了一个简单的扩展方法:
public static object GetReflectedProperty(this object obj, string propertyName)
{
obj.ThrowIfNull("obj");
propertyName.ThrowIfNull("propertyName");
PropertyInfo property = obj.GetType().GetProperty(propertyName);
if (property == null)
{
return null;
}
return property.GetValue(obj, null);
}
Run Code Online (Sandbox Code Playgroud)
然后我只是用它来对我的Json数据做断言:
JsonResult result = controller.MyAction(...);
...
Assert.That(result.Data, Is.Not.Null, "There should be some data for the JsonResult");
Assert.That(result.Data.GetReflectedProperty("page"), Is.EqualTo(page));
Run Code Online (Sandbox Code Playgroud)
我参加派对有点晚了,但是我创建了一个小包装器,让我可以使用dynamic属性.在这个答案中,我已经开始使用ASP.NET Core 1.0 RC2,但我相信如果你resultObject.Value用resultObject.Data它替换它应该适用于非核心版本.
public class JsonResultDynamicWrapper : DynamicObject
{
private readonly object _resultObject;
public JsonResultDynamicWrapper([NotNull] JsonResult resultObject)
{
if (resultObject == null) throw new ArgumentNullException(nameof(resultObject));
_resultObject = resultObject.Value;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (string.IsNullOrEmpty(binder.Name))
{
result = null;
return false;
}
PropertyInfo property = _resultObject.GetType().GetProperty(binder.Name);
if (property == null)
{
result = null;
return false;
}
result = property.GetValue(_resultObject, null);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
用法,假设以下控制器:
public class FooController : Controller
{
public IActionResult Get()
{
return Json(new {Bar = "Bar", Baz = "Baz"});
}
}
Run Code Online (Sandbox Code Playgroud)
测试(xUnit):
// Arrange
var controller = new FoosController();
// Act
var result = await controller.Get();
// Assert
var resultObject = Assert.IsType<JsonResult>(result);
dynamic resultData = new JsonResultDynamicWrapper(resultObject);
Assert.Equal("Bar", resultData.Bar);
Assert.Equal("Baz", resultData.Baz);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29416 次 |
| 最近记录: |