I have upgraded the version of Rebus.6.7.0 to 7.2.0 and Rebus.TestHelpers.7.2.0 to 8.0.0 and a unit test that was previously passing is now failing due to a desterilisation change.
The unit test creates a SagaFixture and delivers an event message SomethingFailedEvent
which contains a property of type Exception
. The exception type assigned is typeof(ArgumentException)
with a custom message "Invalid Argument".
Within the Saga; the SomethingFailedEvent
message handler publishes a new event message FailedResponse
with a string property ErrorMessage
set to the incoming event messages Exception.Message
property.
The test then asserts that a FailedResponse
message was published with a ErrorMessage
property set to the SomethingFailedEvent
Exception's message.
The test failure is caused by the fact that System.Text.Json is used for deserialisation which doesn't support polymorphic types (pre .NET 7.0). So when the SomethingFailedEvent
message is delivered to the Saga the Exception type is desearlised to System.Exception and not the intended type ArgumentException
and thus the Exception.Message
property is 'Exception of type 'System.Exception' was thrown.' which causes the assert to fail.
Code snippets below create a representation of the above scenario.
/// Event Types
public class SomethingFailedEvent
{
public Exception Exception { get; set; }
}
public class FailedResponse
{
public string ErrorMessage { get; set; }
}
/// SagaFixture Event Handler
public async Task Handle(SomethingFailedEvent message)
{
var failedEvent = new FailedResponse
{
ErrorMessage = message.Exception.Message
};
await Bus.Publish(failedEvent);
}
Unit Test Code Snippet
[Test]
public void FailureEventReceivedCanPublishFailedMessageWithExceptionDetails()
{
var bus = new FakeBus();
var logger = new NullLogger<MockSaga>();
var sagaFixture = SagaFixture.For(
() => new MockSaga(logger, bus);
var startSagaEvent = new MockSagaRequested();
sagaFixture.Deliver(startSagaEvent);
var argumentException = new ArgumentException("Invalid Argument");
var somethingFailedEvent = new SomethingFailedEvent()
{
Exception = argumentException
};
sagaFixture.Deliver(failedEvent);
var failedEventMessage = bus.Events.OfType<MessagePublished<FailedResponse>>().Single();
failedEventMessage.EventMessage.ErrorMessage.Should().Contain("Invalid Argument");
}
Is it possible to support creating the FakeBus
and setting the serialisation to be Newtonsoft.Json similarly to when configuring Rebus.
.Serialization(s => s.UseNewtonsoftJson(
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Auto
}))
It sounds like you'll simply have to configure the saga fixture's message serializer, which can be done like this:
static RebusConfigurer GetConfigurer() => Configure
.With(new BuiltinHandlerActivator())
.Serialization(s => s.UseNewtonsoftJson());
using var fixture = SagaFixture.For<SomeSaga>(GetConfigurer);
fixture.Deliver(new SomeMessageWithLoop());
You can see the test fixture for the feature here: https://github.com/rebus-org/Rebus.TestHelpers/blob/master/Rebus.TestHelpers.Tests/TestSagaFixture_CustomMessageSerializer.cs