rebus-org / Rebus.TestHelpers

:bus: Test helpers for Rebus (i.e. fake bus, saga fixture, etc.)
https://mookid.dk/category/rebus
Other
4 stars 2 forks source link

Is it possible to use Newtonsoft.Json with FakeBus? #13

Closed vinydanylo closed 1 year ago

vinydanylo commented 1 year ago

Hi there πŸ‘‹πŸ½ it's my first time writing an issue on GitHub! Thanks for the open space and I hope I'm doing it right πŸ˜…

So some of my DTOs have looping references and it's not a problem as I configured Rebus to use NewtonSoft.Json. I have upgraded to Rebus 7.0 and, therefore to Rebus.TextHelpers 8.0. I've read that Rebus now uses System.Text.Json as default Json serializer, therefore FakeBus as well. The problem I have now is that System.Text.Json can't handle my DTOs. I looked on the Wiki but I could not find a way to set the JsonSerializer of FakeBus.

I just want to restate that the application is running fine with the new Rebus, my only problem is with Unit Tests.

Do you have any suggestion?

Here I've pasted some code snippets.


public class ChangeParentCommand {
    public ChangeParentCommand(Guid processingId) {
        ProcessingId = processingId;
    }

    public Guid ProcessingId { get; set; }

    [JsonProperty(IsReference = true,
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        ItemReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        TypeNameHandling = TypeNameHandling.All
    )]
    public ICollection<ParentDto> Parents { get; set; } = new List<ParentDto>();
}

[JsonObject(IsReference = true, ItemTypeNameHandling = TypeNameHandling.All)]
public class Parent {
    [JsonProperty(IsReference = true,
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        ItemReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        TypeNameHandling = TypeNameHandling.All
    )]
    public ICollection<ChildDto> Children { get; set; } = new List<ChildDto>();
}

[JsonObject(IsReference = true, ItemTypeNameHandling = TypeNameHandling.All)]
public class Child {
    [JsonProperty(IsReference = true,
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        ItemReferenceLoopHandling = ReferenceLoopHandling.Serialize,
        TypeNameHandling = TypeNameHandling.All
    )]
    public ICollection<ParentDto> Parents { get; set; } = new List<ParentDto>();
}

// on my unit tests:
    [Fact]
    public void HandleChangeParentCommand() {
        var message = new ChangeParentCommand(Guid.NewGuid()) {
            Parents = someData.ToList(),
        };

        var fakeBus = new FakeBus();
        using var fixture = SagaFixture.For(() => new ChangeParentSaga(fakeBus));

        fixture.Add(new ChangeParentSagaData {
                ProcessingStepTrackingId = message.SagaCorrelationId,
                Step = "Some Step",
            }
        );

        fixture.Deliver(message); // error on sending

        var data = fixture.Data.OfType<ChangeParentSagaData>();

        data.Should().NotBeEmpty();
    }
# error thrown
System.Text.Json.JsonException
A possible object cycle was detected. This can either be due to a cycle or
if the object depth is larger than the maximum allowed depth of 64. Consider 
using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
mookid8000 commented 1 year ago

FakeBus doesn't do any serialization, it's actually the SagaFixture thing that runs a full bus behind the scenes.

And I believe this is an oversight on my part, as e.g. I would want SagaFixture to be able to provide a realistic experience also when using e.g. Protobuf to serialize message, and so it should be configurable.

Let me just take a look. Maybe I will release an update in a few hours πŸ™‚

mookid8000 commented 1 year ago

OK it turned out that it was actually possible πŸ™‚

Check out this test case that I've just added.

In the test I created a local method GetConfigurer that returns a RebusConfigurer that has Newtonsoft JSON.NET configured. This way it seems like loops can be serialized just fine. πŸ™‚

Let me know if it doesn't work like you expected.

vinydanylo commented 1 year ago

Yep, I just got the test run and your solution worked like a charm! Thanks a lot for your help and for making Rebus great!