Asserting Rest Functional Tests

I’ve been doing a lot of work with Rest services lately. Since I’ve been able to use .Net 4.5 this has meant using WebAPI and, luckily enough, I have been able to put together a nice decoupled, unit tested stack (@500 unit tests 65% code coverage), leveraging dependency injection and WebApi’s more decoupled nature than WCF.

As I’ve been adding functional tests around completed functionality I’ve had to find a quick way in C# to parse our returned json into something that can be understood in C#. At first I started parsing the returned json as a string and looking for particular structures in the string. Looked something like this:

requestUri = new Uri("http://localhost/api/students/34");

//--base test class method to prepare web request
PrepareGetService(requestUri);

//--base test class method to execute web request
var result = GetResponse(requestUri);

Assert.IsTrue(result.Contains("firstName:""John,"), "Bad First Name.");

The above has some obvious problems.

  • FirstName could exist elsewhere in my model
  • The spacing could be different than what I’m expecting in the returned json
  • Firstname could be the last field and have no comma
  • If I take the comma off FirstName could match “Johnny” as well as “John”, etc
  • There is no guarantee this is a model at all, could be just that string that is returned

I did a little googling and found that I can parse a json object into a C# dictionary fairly quickly:

var resultObj = new JavaScriptSerializer().DeserializeObject(result) as Dictionary<string, object>;

Assert.AreEqual("John", resultObj["firstName"], "Bad First Name.");

This is a little better as now I know the exact field and value and can compare them discreetly. It won’t matter where in the json FirstName is, and if the response is not deserializable into a dictionary I probably have some badly formatted json, which is also good to know.

When I realized I could deserialize into a c# object it dawned on me I could just serialize into the c# model, if I have one. Then this would work:

var resultObj = new JavaScriptSerializer().DeserializeObject(result) as Student;

Assert.AreEqual("John", resultObj.FirstName, "Bad First Name.");

The above is great as long as the json was created from serializing a type in my c# code, in this case student. This is not always the case, as sometimes the return objects are being dynamically created as anonymous types:

 public HttpResponseMessage Get(int id)
        {
            IRestContext context = _restContextProvider.GetContext(Request);
           
            Student stuudent = _studentRepository.GetStudent(id);

            return context.CreateResponse(HttpStatusCode.Ok, new { firstName = student.FirstName, lastName = student.LastName, pullDate = DateTime.UtcNow });           
        }

In the above I’ll have no type to deserialize into, but the dictionary should work just fine for this.

In short parsing strings for checking json results in my functional tests had some issues, so went to using explicit types where possible, and a dictionary where getting back anonymous types.