2011-11-10 95 views
0

在一个成功的AJAX调用的事件我想回到一个简单的对象与Success = true单元测试一个简单的JsonResult的最佳方法是什么?

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}] 

有一个简单,干净的方式实现什么似乎像它应该很容易,或者是执行一些自定义序列作为链接​​的问题的唯一途径?

+0

您在单元测试中得到的result.Data不能包含json数据,因为jsonResult序列化程序仅在ExecuteResult方法中运行,该方法未在单元测试中运行。 result.Data中的“数据”只是您在AddNote/Foo操作中分配的匿名数据。你测试的不是json数据! – Elisabeth

回答

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. 您必须使用某种序列化解决方法,如您所述。

+0

'InternalsVisibleTo'传奇! –

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

+1

你从哪里得到'JSONText'?在单元测试中,你没有通过网络的实际HTTP体... –

相关问题