public void Onboarding_Causes_An_Account_To_Be_Created_For_The_Customer() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); fixture.SagaDataShould( have: x => x.CustomerName == customerName, because: "store the customer name") .SagaDataIsNotComplete(); bus.HasSentLocal <CreateCustomerAccount>( with: x => x.CustomerName == customerName, because: "it should initiate account creation" ); fixture.Deliver(new CustomerAccountCreated { CustomerName = customerName }); fixture.SagaDataShould( have: x => x.AccountCreated, because: "it should remember the account has been created") .SagaDataIsNotComplete(); fixture.ShouldNotHaveCompleted(); } }
public void CanCorrectlySerializeAndDeserializeCaspersSagaData() { // arrange var fixture = new SagaFixture <SagaData>(new Saga()); // act fixture.Handle(new Message { CorrelationId = 42, String = "hello there" }); fixture.Handle(new Message { CorrelationId = 42, String = "hello again!" }); // assert fixture.AvailableSagaData.Count() .ShouldBe(1); var sagaData = fixture.AvailableSagaData.Single(); sagaData.ReceivedStrings.ShouldContain("hello there"); sagaData.ReceivedStrings.ShouldContain("hello again!"); var concreteClass = (ConcreteClass)sagaData.RefToAbstractClass; concreteClass.WithWhat.ShouldBe("something in it"); }
public void CanSimulateConflict_MultipleMessages_SingleConflict() { using (var fixture = SagaFixture.For(() => new ConflictSagaHandler())) { fixture.DumpLogsOnDispose(); fixture.Deliver(new SomeMessage("some-id", "HEJ MED DIG")); fixture.Deliver(new SomeMessage("some-id", "MIN VEN")); fixture.PrepareConflict <ConflictSagaHandlerData>(d => d.CorrelationId == "some-id"); fixture.Deliver(new SomeMessage("some-id", "IGEN")); var sagaData = fixture.Data .OfType <ConflictSagaHandlerData>() .FirstOrDefault(d => d.CorrelationId == "some-id") ?? throw new AssertionException($"Could not find saga data with correlation ID 'some-id'"); string GetReceivedStrings() => $@"Got these strings: {string.Join(Environment.NewLine, sagaData.ReceivedStrings)} "; Assert.That(sagaData.ReceivedStrings.Count, Is.EqualTo(3), GetReceivedStrings); Assert.That(sagaData.ReceivedStrings.Contains("HEJ MED DIG"), Is.True, GetReceivedStrings); Assert.That(sagaData.ReceivedStrings.Contains("MIN VEN"), Is.True, GetReceivedStrings); Assert.That(sagaData.ReceivedStrings.Contains("IGEN"), Is.True, GetReceivedStrings); } }
public void The_Sales_Team_Will_Set_Up_A_Call_With_The_Customer_After_Their_Account_Has_Been_Created() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); fixture.Deliver(new CustomerAccountCreated { CustomerName = customerName }); fixture.SagaDataShould( have: x => x.AccountCreated, because: "it should remember the account has been created") .SagaDataIsNotComplete(); bus.HasSentLocal <ScheduleASalesCall>( with: x => x.CustomerName == customerName, because: "a sales call is scheduled after the account is created"); fixture.ShouldNotHaveCompleted(); } }
public void Other_Systems_Are_Notified_After_A_Succcessful_Onboarding() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); fixture.Deliver(new CustomerAccountCreated { CustomerName = customerName }); fixture.Deliver(new WelcomePackSentToCustomer { CustomerName = customerName }); fixture.ShouldHaveCompleted(); bus.HasPublished <CustomerOnboarded>( with: x => x.CustomerName == customerName, because: "the saga should publishes an event notifying of the customer onboarding") .HasNotSentLocal <CustomerOnboardingOlaBreached>( because: "the onboarding was successful"); fixture.ShouldHaveCompleted(); OnboardCustomerSagaData SagaDataShould(Predicate <OnboardCustomerSagaData> have, string because = null) { return(fixture.SagaData <OnboardCustomerSaga, OnboardCustomerSagaData>().Should(have, because)); } } }
public void CanCorrelateMessagesLikeExpected() { // arrange var fixture = new SagaFixture <SomeSagaData>(new SomeSaga()); fixture.CreatedNewSagaData += (message, data) => Console.WriteLine("Created new saga data"); fixture.CorrelatedWithExistingSagaData += (message, data) => Console.WriteLine("Correlated with existing saga data"); fixture.CouldNotCorrelate += message => Console.WriteLine("Could not correlate"); // act fixture.Handle(new SomeMessage { SagaDataId = 10 }); fixture.Handle(new SomeMessage { SagaDataId = 10 }); fixture.Handle(new SomeMessage { SagaDataId = 12 }); fixture.Handle(new SomeMessage { SagaDataId = 12 }); fixture.Handle(new SomeMessage { SagaDataId = 12 }); // assert var availableSagaData = fixture.AvailableSagaData; availableSagaData.Count().ShouldBe(2); availableSagaData.Single(d => d.SagaDataId == 10).ReceivedMessages.ShouldBe(2); availableSagaData.Single(d => d.SagaDataId == 12).ReceivedMessages.ShouldBe(3); }
public void A_Welcome_Pack_Is_Sent_To_The_Customer_After_Their_Account_Has_Been_Created() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); fixture.Deliver(new CustomerAccountCreated { CustomerName = customerName }); fixture.SagaDataShould( have: x => x.AccountCreated, because: "it should remember the account has been created") .SagaDataIsNotComplete(); bus.HasSent <SendWelcomePackToCustomer>( with: x => x.CustomerName == customerName, because: "it should initiate welcome pack creation" ); fixture.ShouldNotHaveCompleted(); } }
public void CanCorrectlyHandleWhenSagaIsMarkedAsComplete() { // arrange var fixture = new SagaFixture <CompletionSagaData>(new CompletionSaga()); const string justTheSameFrigginId = "just the same friggin ID"; var sagaDatasMarkedAsComplete = new List <ISagaData>(); fixture.MarkedAsComplete += (message, data) => sagaDatasMarkedAsComplete.Add(data); fixture.CorrelatedWithExistingSagaData += (message, data) => Console.WriteLine("Correlated!"); fixture.CouldNotCorrelate += message => Console.WriteLine("Could not correlate!"); fixture.CreatedNewSagaData += (message, data) => Console.WriteLine("Created new!"); fixture.Exception += (message, exception) => Console.WriteLine("Exception!"); // act fixture.Handle(new InitiatingMessage { CorrelationId = justTheSameFrigginId }); fixture.Handle(new CompletionMessage { CorrelationId = justTheSameFrigginId }); fixture.Handle(new InitiatingMessage { CorrelationId = justTheSameFrigginId }); fixture.Handle(new CompletionMessage { CorrelationId = justTheSameFrigginId }); // assert sagaDatasMarkedAsComplete.Count.ShouldBe(2); fixture.DeletedSagaData.Count.ShouldBe(2); }
public void EventAreFiredInTheRightPlaces(string scenario) { var events = new List <string>(); const string justTheSameFrigginId = "just the same friggin ID"; var fixture = new SagaFixture <CompletionSagaData>(new CompletionSaga()); fixture.MarkedAsComplete += (msg, data) => events.Add("markedAsComplete"); switch (scenario) { case "mark persistent saga data as complete": fixture.Handle(new InitiatingMessage { CorrelationId = justTheSameFrigginId }); fixture.Handle(new CompletionMessage { CorrelationId = justTheSameFrigginId }); break; case "mark non-persistent saga data as complete": fixture.Handle(new InitiateAndCompleteMessage { CorrelationId = justTheSameFrigginId }); break; default: throw new ArgumentException(string.Format("Unknown scenario: {0}", scenario)); } events.ShouldContain("markedAsComplete"); }
public void WorksWhenMessageReferenceIsOfTheSupertype() { // arrange var data = new CounterpartData { Dcid = 800 }; var calledHandlers = new List <string>(); var fixture = new SagaFixture <CounterpartData>(new CounterpartUpdater(calledHandlers)); fixture.AddSagaData(data); CounterpartChanged messageSupertype1 = new CounterpartCreated { Dcid = 800 }; CounterpartChanged messageSupertype2 = new CounterpartUpdated { Dcid = 800 }; // act // assert fixture.Handle(messageSupertype1); fixture.Handle(messageSupertype2); calledHandlers.ShouldBe(new List <string> { "CounterpartCreated", "CounterpartUpdated", }); }
public void If_The_Ola_Is_Breached_Then_Any_Placed_Sales_Call_Is_Cancelled() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); fixture.Deliver(new CustomerAccountCreated { CustomerName = customerName }); bus.HasSentLocal <ScheduleASalesCall>( with: x => x.CustomerName == customerName, because: "a sales call is scheduled after the account is created"); fixture.Deliver(new VerifyCustomerOnboardingOla { CustomerName = customerName }); fixture.ShouldHaveCompleted(); bus.HasSentLocal <CancellSalesCall>( with: x => x.CustomerName == customerName, because: "any scheduled sales call is cancelled after an OLA breach"); } }
public static void DumpLogsOnDispose <TSagaHandler>(this SagaFixture <TSagaHandler> sagaFixture) where TSagaHandler : Saga { sagaFixture.Disposed += () => { Console.WriteLine(string.Join(Environment.NewLine, sagaFixture.LogEvents)); }; }
public void CanRetrieveSagaData() { using var fixture = SagaFixture.For <MySaga>(); fixture.Deliver(new TestMessage("hej")); var current = fixture.Data.OfType <MySagaState>().ToList(); Assert.That(current.Count, Is.EqualTo(1)); Assert.That(current[0].Text, Is.EqualTo("hej")); }
public static void DumpLogsOnDispose <TSagaHandler>(this SagaFixture <TSagaHandler> sagaFixture) where TSagaHandler : Saga { if (sagaFixture == null) { throw new ArgumentNullException(nameof(sagaFixture)); } sagaFixture.Disposed += () => { Console.WriteLine(string.Join(Environment.NewLine, sagaFixture.LogEvents)); }; }
public void EmitsCouldNotCorrelateEvent() { using (var fixture = SagaFixture.For <MySaga>()) { var gotEvent = false; fixture.CouldNotCorrelate += () => gotEvent = true; fixture.Deliver(new TestMessage("hej")); Assert.That(gotEvent, Is.True); } }
public void EmitsCreatedEvent() { using var fixture = SagaFixture.For(sagaHandlerFactory: () => new MySaga(), sagaSerializerFactory: () => new MicrosoftSagaSerializer()); var gotEvent = false; fixture.Created += _ => gotEvent = true; fixture.Deliver(new TestMessage("hej")); Assert.That(gotEvent, Is.True); }
public void EmitsCreatedEvent() { using (var fixture = SagaFixture.For <MySaga>()) { var gotEvent = false; fixture.Created += d => gotEvent = true; fixture.Deliver(new TestMessage("hej")); Assert.That(gotEvent, Is.True); } }
public void AddShouldAddToAvailableSagaData() { var someSagaData = new SomeSagaData { JustSomeText = Guid.NewGuid().ToString() }; var fixture = new SagaFixture <SomeSagaData>(new SomeSaga()) { someSagaData }; fixture.OfType <SomeSagaData>().First().JustSomeText.ShouldBe(someSagaData.JustSomeText); }
public void EmitsUpdatedEvent() { using var fixture = SagaFixture.For <MySaga>(); fixture.Deliver(new TestMessage("hej")); var gotEvent = false; fixture.Updated += _ => gotEvent = true; fixture.Deliver(new TestMessage("hej")); Assert.That(gotEvent, Is.True); }
public void Reproduce() { using var fixture = SagaFixture.For(() => new MySaga()); fixture.DumpLogsOnDispose(); fixture.Deliver(new MyMessage()); Task.Delay(TimeSpan.FromSeconds(1)).Wait(); var logs = fixture.LogEvents.ToList(); Assert.That(logs.Count(l => l.Level == LogLevel.Warn), Is.EqualTo(1)); }
public void IdIsSetUponNullId() { using (var fixture = SagaFixture.For <MySaga>()) { // Arrange // Act fixture.Add(new MySagaState()); // Asert Assert.That(fixture.Data.Count(), Is.EqualTo(1)); Assert.That(fixture.Data.Single().Id, Is.Not.Null); } }
public void CanSetUpFakeSagaData() { using var fixture = SagaFixture.For <MySaga>(); fixture.Add(new MySagaState { Text = "I know you!" }); fixture.AddRange(new[] { new MySagaState { Text = "I know you too!" } }); Assert.That(fixture.Data.Count(), Is.EqualTo(2)); Assert.That(fixture.Data.OfType <MySagaState>().Count(d => d.Text == "I know you!"), Is.EqualTo(1)); Assert.That(fixture.Data.OfType <MySagaState>().Count(d => d.Text == "I know you too!"), Is.EqualTo(1)); }
public void The_Systems_Track_The_Ola_For_Customer_Onboarding() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); bus.HasDeferredLocal <VerifyCustomerOnboardingOla>( with: x => x.CustomerName == customerName, because: "it should start tracking the OLA"); } }
public void SagaDataWithNonEmptyIdIsAddedToSagaFixtureData() { using (var fixture = SagaFixture.For <MySaga>()) { // Arrange // Act fixture.Add(new MySagaState { Id = Guid.NewGuid() }); // Assert Assert.That(fixture.Data.Count(), Is.EqualTo(1)); } }
public void CanDispatchFailedMessage() { var failedMessageWasReceived = new ManualResetEvent(false); Using(failedMessageWasReceived); using var fixture = SagaFixture.For(() => new MySaga(failedMessageWasReceived), secondLevelRetriesEnabled: true); fixture.DumpLogsOnDispose(); fixture.Add(new MySagaState { Text = "known-string" }); fixture.DeliverFailed(new TestMessage("known-string"), new DriveNotFoundException("B:")); failedMessageWasReceived.WaitOrDie(TimeSpan.FromSeconds(3)); }
public async Task YeahItWorks() { var receivedEvents = new ConcurrentQueue <string>(); using var fixture = SagaFixture.For(() => new RandomSaga(receivedEvents)); fixture.Deliver(new RandomMessage("hej")); fixture.HandlerExceptions.ThrowIfNotEmpty(); await Task.Delay(millisecondsDelay : 17); fixture.Deliver(new RandomMessage("hej igen")); Assert.That(receivedEvents.Count, Is.EqualTo(2)); Assert.That(receivedEvents, Is.EqualTo(new[] { "hej", "hej igen" })); }
public void CanGetCaughtException() { using (var fixture = SagaFixture.For <MySaga>()) { fixture.Deliver(new FailingTestMessage("whoohoo")); var handlerExceptions = fixture.HandlerExceptions.ToList(); Console.WriteLine(string.Join(Environment.NewLine + Environment.NewLine, handlerExceptions)); Assert.That(handlerExceptions.Count, Is.EqualTo(1)); var exception = handlerExceptions.Single(); Assert.That(exception.Exception, Is.TypeOf <RebusApplicationException>()); Assert.That(exception.Exception.ToString(), Contains.Substring("oh no something bad happened")); } }
public void GetsHumanReadableExceptionWhenSomethingGoesWrong() { // arrange var data = new List <SomeSagaData> { new SomeSagaData { SagaDataId = 23 } }; var fixture = new SagaFixture <SomeSagaData>(new SomeSaga(), data); // act var exception = Assert.Throws <ApplicationException>(() => fixture.Handle(new SomePoisonMessage { SagaDataId = 23 })); Console.WriteLine(exception.ToString()); // assert exception.Message.ShouldContain("Oh no, something bad happened while processing message with saga data id 23"); }
public void ThrowsProperExceptionWhenAttemptingToEstablishMessageContextWithItemsDictionary() { var saga = new SearchSaga(); var fixture = new SagaFixture <SearchSagaData>(saga); var fakeContext = MockRepository.GenerateMock <IMessageContext>(); fakeContext.Stub(s => s.ReturnAddress).Return("queuename"); fakeContext.Stub(s => s.Headers).Return(new Dictionary <string, object>()); // act var ex = Assert .Throws <ArgumentException>(() => { using (FakeMessageContext.Establish(fakeContext)) { fixture.Handle("w00000t!"); } }); ex.Message.ShouldContain("has null as the Items property"); }
public void If_The_Ola_Is_Breached_Then_And_No_Sales_Call_Was_Placed_Then_No_Cancellation_Takes_Place() { var customerName = RandomName; var bus = new FakeBus(); using (var fixture = SagaFixture.For(() => new OnboardCustomerSaga(bus))) { fixture.Deliver(new OnboardCustomer { CustomerName = customerName }); bus.HasNotSentLocal <ScheduleASalesCall>( because: "the account creation is has not been confirmed"); fixture.Deliver(new VerifyCustomerOnboardingOla { CustomerName = customerName }); fixture.ShouldHaveCompleted(); bus.HasNotSentLocal <CancellSalesCall>( because: "the sales call is only cancelled after an OLA breach if it has already been requested"); } }