单元测试一个简单的JsonResult的最佳方法是什么?

时间:2011-11-10 18:11:41

标签: asp.net-mvc-3 dynamic expandoobject

如果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是一团糟,as detailed in this question

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

是否有一种简单,干净的方式来实现看似简单的方法,或者是在链接问题中实现某些自定义序列化的唯一方法?

2 个答案:

答案 0 :(得分:1)

  1. 如果使用dynamic标记控制器程序集,则[assembly: InternalsVisibleTo("TestsProject")]的值可以正常工作。因为为匿名类型生成的类是内部的,而运行时绑定不适用于内部类型。在此article中,您可以找到有关此内容的更多信息。
  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. 您必须使用某种序列化解决方法。

答案 1 :(得分: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反序列化为新的动态对象。
  4. 这样做的缺点是你的json对象上没有IntelliSense,因此编译器不会捕获任何拼写错误。

    注意:我在stackoverflow中编写了代码,因此可能存在一些小错误。我没有测试它,但它应该工作:P