Search code examples
c#json.netunit-testingfluent-assertions

FluentAssertions object graph comparison including JSON objects


I have a simple class with a property of type object, which can contain JSON built from different sources

public class SimpleClass
{
    public string Id { get; set; }
    public object JSONData { get; set; }
}

I'm using FluentAssertions object graph comparison but this isn't working

private void Verify(SimpleClass actualOutput, SimpleClass expectedOutput)
{
    actualOutput.Should().BeEquivalentTo(expectedOutput);
}

Depending on the source of the objects, I'm seeing messages like these

Expected member JSONData to be a 
System.Collections.Generic.IDictionary`2[System.String,Newtonsoft.Json.Linq.JToken], but found a 
System.Text.Json.JsonElement.

Expected member JSONData to be 
System.String, but found 
System.Text.Json.JsonElement.

The objects are equal when I convert them to strings

private void Verify(SimpleClass actualOutput, SimpleClass expectedOutput)
{
    actualOutput.JSONData.ToString().Should().Be(expectedOutput.JSONData.ToString());
}

I don't want to compare individual properties like that, because I need to compare a collection of SimpleClass instances. Is there any way to make this work using object graph comparison? Can I configure FluentAssertions to do the string conversion during comparison?


Solution

  • [Fact]
    public void CompareJson()
    {
        var jsonText = @"{
      ""Element1"": 123,
      ""Element2"": ""text""
    }";
        var x1 = new SimpleClass { Id = "X", JSONData = jsonText };
        var x2 = new SimpleClass { Id = "X", JSONData = JsonConvert.DeserializeObject(x1.JSONData.ToString()) };
    
        x1.Should().BeEquivalentTo(
            x2,
            o => o.Using<object>(ctx => ctx.Subject.ToString().Should().Be(ctx.Expectation.ToString())).When(
                info => info.SelectedMemberPath.EndsWith(nameof(SimpleClass.JSONData))));
    }