一尘不染

如何对返回JsonResult的Action方法进行单元测试?

json

如果我有这样的控制器:

[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);
}

基本上,我从存储库中获取东西,然后将其投影到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.");
}

但是我在循环中收到一个运行时错误,指出“对象不包含id的定义”。

当我将断点actionResult.Data定义为List<T>匿名类型时,因此我确定是否通过这些类型进行枚举,可以检查属性。在循环内部,该对象
确实 具有一个名为“ id”的属性-因此不确定是什么问题。


阅读 198

收藏
2020-07-27

共1个答案

一尘不染

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);
    }

然后,我只是使用它对我的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));
2020-07-27