Question

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?

Was it helpful?

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.

OTHER TIPS

What you can do is:

var js = new JavaScriptSerializer();
var response = new { id = 0, Status = false };
dynamic object = js.Deserialize(new StringReader(JSONText), response.GetType());

Assert.IsTrue(object.Success)

What this does is:

  1. Create a JavaScriptSerializer.
  2. Create a new anonymous object with the same layout as your json, so the serialiser knows what your object looks like
  3. Deserialize the json into a new dynamic object.

The disadvantage of this is that you will not have IntelliSense on your json object, so any spelling mistake will not be caught by the compiler.

Note: I wrote the code here in stackoverflow, so there might be minor bugs in it. I did not test it, but it should work :P

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top