Search code examples
asp.net-mvc-3dynamicexpandoobject

What is the best way to unit test a simple JsonResult?


In the event of a successful AJAX call I want to return a simple object with Success = true

public ActionResult Foo(int id)
{
    // ...
    return Json(new {Success=true});
}

This works fine and the object my javascript receives looks like

{ Success : true }  

but because the object returned is an anonymous type, I can't do (something like) the following in my test:

var result = (JsonResult)controller.AddNote(id, message);
dynamic data = result.Data;

// Assert
Assert.That(data.Success, Is.EqualTo(true));

So I tried returning an ExpandoObject which allows the test to work in the way I want but the the JSON sent back in the AJAX response is a mess, as detailed in this question.

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

Is there a simple, clean way to achieve what seems like it should be easy, or is the only way to implement some custom serialization as in the linked question?


Solution

    1. Get the value with dynamic can work if you mark your controller assembly with the [assembly: InternalsVisibleTo("TestsProject")]. Because the classes generated for anonymous types are internal and runtime binding does not work with internal types. In this article you can find more information about this.
    2. If you don't like this approach you can fallback to plain old reflection (hidden behind some helper methods):

      [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. Use named classes instead of anonymous ones.

    4. You have to use some kind of serialization workaround as you mentioned.