2011-11-10 98 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體... –

相關問題