Search code examples
c#apiresponsespecflow

How to assert that a API response has a specific structure?


I have a SpecFlow test definition set up where I want to assert that the response have a specific collection of fields in its response. For example I have this particular expected response from the API:

{
    isActive: false,
    lastProcessed: "2020-11-03T19:03:16.537"

}

What I want to verify is that the response contains those two fields, not necessarily the value those fields contain. I tried the following method:

Assert.NotNull(response.Model.isActive);
Assert.NotNull(response.Model.lastProcessed);

But I'm getting an error using this method: Do not use Assert.NotNull() on value type 'bool'

How else can I make sure the response structure is as expected other than using "NotNull()"?

The Solution: Following the accepted answer, I serialized the model returned from the API call into JSON and parsed it into a JObject. Then I used the ContainsKey() method to assert it.

JObject jObject = JObject.Parse(JsonConvert.SerializeObject(response.Model));
Assert.True(jObject.ContainsKey("isActive"));

Solution

  • I don't know what packages you use for sending requests and deserialization but if you could get the response content as a raw json string you could then use Newtonsoft.JSON to parse the response into a JObject with JObject.Parse(responseContent). JObject has a method called ContainsKey(propertyName) which determines whether there is a field of a specified name in the object. You could assert if it returns true for the desired property names.

    Edit

    Regarding Greg's answer below. The original error is in fact caused by bool not being a nullable type and making it nullable in the model would fix the error. However, this solution is not ideal. In some cases null can be a valid value returned by the API and this would generate false negatives. e.g. if we recieved:

    {
        isActive: null,
        lastProcessed: "2020-11-03T19:03:16.537"
    }
    

    then Assert.NotNull(response.Model.isActive) would yield a negative test result even though the field is present in the json, and that's what we wanted to check.

    So theoretically if we are 100% sure that null will never be returned by the API itself, then we could do it that way, but it won't be a universal method. Also not very descriptive of what we are trying to achieve ;)