Olivier Muhring

Olivier Muhring

  • 1.4k
  • 262
  • 8.9k

C# - JSON validation in unit test

Feb 18 2024 1:12 PM

On a project, running on .NET 4.8 I'm executing a call to a web service, this call then returns a JSON, which needs to be processed.

I created the C# classes (long live jjson2csharp.com)and decided to write a unit test to validate classes. In other words, to check if the generated classes are a good fit for the data being offered.

I did a bit of research on the subject and found a couple of usable references:

  • damirscorner.com/blog/posts/20220520-ComparingJsonStringsInUnitTests.html
  • stackoverflow.com/questions/52645603/how-to-compare-two-json-objects-using-c-sharp

As more or less demonstrated in my examples, I'm loading the JSON from a file, parsing it into objects as I do in the actual code, and then check whether or not what's in the objects corresponds with the JSON file.

Serialization and deserialization aren't creating issues, the verification however...

The JSON response provided by the web service is rather lengthy, a complex nested structure. Certain of the items can even be found several times in the same response, alone or as part of a different sub-structure.

Of course, in C# this means reusing the same class, but... in certain cases, one instance of data the numbers are displayed in decimal format, in others as plain integers.

This is a very simplified JSON of course.

As a result, when I run my unit test, it fails. It gets a float where it expects an int or one time an int is expected, and other times a float:

I attempted to solve this by creating multiple versions of the impacted classes, but... sometimes modifying the type to what the unit test expects breaks the conversion itself. T The unit test looks like his:

[TestClass]
public class CheckSerializationOfRequestAndResponseJsons : TestsBase
{
    [TestMethod]
    public void ResponseJsons_ShouldBeEqualAsExpected()
    {
        var expectedJson = LoadJson("SomeJson.json");

        //  Generate a base object model using a generalized structure
        var expected = JToken.Parse(expectedJson);

        //  Generating an object model using the defined classes
        var actualModel = JsonConvert.DeserializeObject<JsonContainer>(expectedJson);

        //  Converting the new object back into json
        var actualJson = JsonConvert.SerializeObject(actualModel);

        //  Generating a new object using a generalized structure
        var actual = JToken.Parse(actualJson);

        //  Comparing the 2
        actual.Should().BeEquivalentTo(expected);
    }
}

My Dto's look like this:

/// <summary>Tax</summary>
public class Tax
{
    /// <summary>Tax - total charge</summary>
    [JsonProperty("tax", NullValueHandling = NullValueHandling.Ignore)]
    public double? Tax;
}

I'm not going to include the entire code, since that's a bit outside of the scope of my question.

The approach used is based on FluentAssertions.

using FluentAssertions.Json;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Another issue is the capitalisation of the keys. In some cases verification fails because of this:

My question is... what can I do?

  • Is there a way for me to force a certain field to be imported as a float?
  • How can the capitalization be dealt with? (seems to be an issue of Newton Soft)
  • Or is my approach for the unit test the problem?

Answers (2)