Test JSON for .NET
Tags: csharp, dotnet, json, testing
Published: 2024-03-24 09:10:44

Almost all the developers have requirement to write unit test. Sometimes you need to test whether specific JSON text is as expected, what will you decide to implement for it ?

If you want to test whole JSON is same (means JSON-level equivalent) and meantime you have the data model which is just for coming JSON, you can test by normal way everyone knows: deserialize JSON to data model instance, then compare with expected another data model instance.

But there should be other scenarios …

1. you want to compare two JSONs are JSON-equivalent without creating additional data model
2. Further, you want to assert some JSON nodes inside whole JSON body should meet some conditions

**Scenario 1:**

As you know, even if 2 literal strings representing JSON are not text-level same, it is still possible that they are JSON-equivalent, just one simple example:

```
{
  "a": 1,
  "b": 2
}
```

```
{
  "b": 2,
  "a": 1
}
```
They are JSON-equivalent.

Then how to deal with this sort of “equivalent” (Imagine possible recursive cases in future)?

_**Solution**_

There is nuget package ‘**LateApexEarlySpeed.Xunit.Assertion.Json**’, by using that, comparison can be achieved as:

![Equivalent for simple JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1uo8vubh5cqvt9vlftx.png)

this library also considered recursive and format cases:

![Equivalent for complex JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i46i4xn7wsoaec50nurz.png)

When assertion failed, how to better know where the JSON node failed to assert and what is the cause ? Let’s try this assertion statement:

![Different JSON comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dy4vpgvlc9ymj97w7by6.png)

and then you will get following exception to tell that there are different number (**2** and **0**) in JSON location: **/a/1** :

![Assert exception](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fb8gykaxawcw9ji4y8aj.png)

The JSON location ‘**/a/1**’ is with standard [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901) format.

**Scenario 2:**

Now let’s say you don’t need to compare whole JSON body’s equivalent but have more concrete test requirement, for example:

> the JSON needs to have property ‘a’ with any value; have property ‘b’ with array with max length of 2 and each item should have property ‘prop’ with numeric value no large than 10; have property ‘c’ with a value be (JSON-) equivalent to {“c1”:1, “c2”:2}.
> 
> No limit for other factors.

normally you may need to write test for this as:

![Traditional way](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3dj1jl8fqrf5csv3iku.png)

Not only it costs more code, but also imagine if assertion failed inside ‘foreach’ loop, it is hard to get which array item error is from by exception.

_**Solution**_

With help of library ‘**LateApexEarlySpeed.Xunit.Assertion.Json**’, test code can be:

![New way](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py0xzqhvurl358dwpy0c.png)

The code should be straightforward now and it is fluent manner.

Notice the ‘Equivalent’ method mentioned in scenario 1 can also be used for any JSON node location.

Sometimes you want to have custom validation logic unit in specific JSON node. Let’s say you want to

> test value of property ‘c’ should have same numeric values for sub properties ‘c1’ and ‘c2’

then you can write as:

![Support custom validation logic](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/497capbsvk440v9gtwo9.png)

the ‘HasCustomValidation’ method accepts custom validation provider and custom error message provider and has several overloads to select.

If property ‘c2’ is 2 in ‘actualJson’, then assertion will fail from your custom validation code and will get error message you provide:

![Assert exception](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e36vmmf7vsvllwysym3e.png)

The available validation methods are in [wiki](https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema/wiki/Fluent-schema-builder#available-fluent-validation-methods), document is in [repo](https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema).

## Conclusion

This article introduced one powerful and flexible JSON test way which should be able to cover most test requirement for JSON. Hope it helps, any feedback is welcomed and thanks for giving [github star](https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema).

BTW, this JSON assertion extensions is based on core library which targets standard JSONSchema spec and the core library is also in same [repo](https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema).