public async Task Verify_update_idempotency()
        {
            var rm = new SampleReadModelTest
            {
                Id      = new TestId(1),
                Value   = "test",
                Counter = 10,
            };
            await sut.InsertAsync(new SampleAggregateCreated(), rm).ConfigureAwait(false);

            //now try to update counter with an event
            SampleAggregateTouched e = new SampleAggregateTouched();

            await sut.FindAndModifyAsync(e, rm.Id, _ => _.Counter++).ConfigureAwait(false);

            var reloaded = await sut.FindOneByIdAsync(rm.Id).ConfigureAwait(false);

            Assert.That(reloaded.Counter, Is.EqualTo(11));

            //idempotency on the very same event
            await sut.FindAndModifyAsync(e, rm.Id, _ => _.Counter++).ConfigureAwait(false);

            reloaded = await sut.FindOneByIdAsync(rm.Id).ConfigureAwait(false);

            Assert.That(reloaded.Counter, Is.EqualTo(11));

            //increment on different event
            SampleAggregateTouched anotherEvent = new SampleAggregateTouched();
            await sut.FindAndModifyAsync(anotherEvent, rm.Id, _ => _.Counter++).ConfigureAwait(false);

            reloaded = await sut.FindOneByIdAsync(rm.Id).ConfigureAwait(false);

            Assert.That(reloaded.Counter, Is.EqualTo(12));
        }
Example #2
0
        public async Task Verify_Correct_save_of_aggregate_version()
        {
            var rm = new SampleReadModelTest();

            rm.Id    = new TestId(1);
            rm.Value = "test";
            await sut.InsertAsync(new SampleAggregateCreated()
            {
                Version = 1,
            }, rm).ConfigureAwait(false);

            rm = sut.All.Single();
            Assert.That(rm.AggregateVersion, Is.EqualTo(1));
            Assert.That(rm.Version, Is.EqualTo(1));

            //now generate another event in the very same commit
            var touchedEvent = new SampleAggregateTouched()
            {
                Version = 1,
            };

            await sut.SaveAsync(touchedEvent, rm).ConfigureAwait(false);

            rm = sut.All.Single();
            Assert.That(rm.AggregateVersion, Is.EqualTo(1));
            Assert.That(rm.Version, Is.EqualTo(2));
        }
        public async Task Verify_check_on_creation_by_two_different_event()
        {
            var rm = new SampleReadModelTest
            {
                Id    = new TestId(1),
                Value = "test"
            };
            SampleAggregateCreated e1 = new SampleAggregateCreated();
            await sut.InsertAsync(e1, rm).ConfigureAwait(false);

            SampleAggregateCreated e2 = new SampleAggregateCreated();

            //check we are not able to create a readmodel with two different source events.
            Assert.ThrowsAsync <CollectionWrapperException>(() => sut.InsertAsync(e2, rm));
        }
        public async Task Verify_insert_generates_notification_for_single_call()
        {
            var rm = new SampleReadModelTest();

            rm.Id    = new TestId(1);
            rm.Value = "test";

            //Access property with reflection to set notification
            sut.SetPropertyValue("NotifySubscribers", false);
            await sut.InsertAsync(new SampleAggregateCreated(), rm, true).ConfigureAwait(false);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            _notifyToSubscribersDouble.ReceivedWithAnyArgs().Send(null);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        }
        public async Task Verify_basic_delete()
        {
            var rm = new SampleReadModelTest();

            rm.Id    = new TestId(1);
            rm.Value = "test";
            await sut.InsertAsync(new SampleAggregateCreated(), rm).ConfigureAwait(false);

            var all = sut.All.ToList();

            Assert.That(all, Has.Count.EqualTo(1));

            await sut.DeleteAsync(new SampleAggregateInvalidated(), rm.Id).ConfigureAwait(false);

            all = sut.All.ToList();
            Assert.That(all, Has.Count.EqualTo(0));
        }
        public async Task Verify_basic_update()
        {
            var rm = new SampleReadModelTest();

            rm.Id    = new TestId(1);
            rm.Value = "test";
            await sut.InsertAsync(new SampleAggregateCreated(), rm).ConfigureAwait(false);

            rm.Value = "test2";
            await sut.SaveAsync(new SampleAggregateTouched(), rm).ConfigureAwait(false);

            var all = sut.All.ToList();

            Assert.That(all, Has.Count.EqualTo(1));
            var loaded = all[0];

            Assert.That(loaded.Value, Is.EqualTo("test2"));
        }
        public async Task Verify_disable_check_on_creation_by_two_different_event_honor_offline_events()
        {
            JarvisFrameworkGlobalConfiguration.DisableOfflineEventsReadmodelIdempotencyCheck();
            var rm = new SampleReadModelTest
            {
                Id    = new TestId(1),
                Value = "test"
            };
            SampleAggregateCreated offlineEvent = new SampleAggregateCreated();
            SampleAggregateCreated onlineEvent  = new SampleAggregateCreated();

            onlineEvent.SetPropertyValue(_ => _.Context, new Dictionary <string, Object>());
            onlineEvent.Context.Add(MessagesConstants.OfflineEvents, new DomainEvent[] { offlineEvent });

            await sut.InsertAsync(offlineEvent, rm).ConfigureAwait(false);

            //this should NOT be ignored, because I've disabled the readmodelidempotency check.
            Assert.ThrowsAsync <CollectionWrapperException>(async() => await sut.InsertAsync(onlineEvent, rm));
        }
        public async Task Verify_check_on_creation_by_two_different_event_honor_offline_events()
        {
            JarvisFrameworkGlobalConfiguration.EnableOfflineEventsReadmodelIdempotencyCheck();
            var rm = new SampleReadModelTest
            {
                Id    = new TestId(1),
                Value = "test"
            };
            SampleAggregateCreated offlineEvent = new SampleAggregateCreated();
            SampleAggregateCreated onlineEvent  = new SampleAggregateCreated();

            onlineEvent.SetPropertyValue(_ => _.Context, new Dictionary <string, Object>());
            onlineEvent.Context.Add(MessagesConstants.OfflineEvents, new DomainEvent[] { offlineEvent });

            await sut.InsertAsync(offlineEvent, rm).ConfigureAwait(false);

            //this should be ignored, because the online event was generated with the same command of the offlineEvent
            //and this should simply skip the insertion.
            await sut.InsertAsync(onlineEvent, rm).ConfigureAwait(false);
        }
        public async Task Verify_generate_notification_on_last_event_generates_notification_on_intermediate_events()
        {
            var rm = new SampleReadModelTest();

            rm.Id    = new TestId(1);
            rm.Value = "test";
            await sut.InsertAsync(new SampleAggregateCreated(), rm).ConfigureAwait(false);

            //Access property with reflection to set notification
            sut.SetPropertyValue("NotifySubscribers", true);
            sut.SetPropertyValue("NotifyOnlyLastEventOfCommit", true);

            SampleAggregateCreated e = new SampleAggregateCreated();

            e.SetPropertyValue(_ => _.IsLastEventOfCommit, true);

            await sut.SaveAsync(e, rm).ConfigureAwait(false);

            //No notification should be sent, because this is not the last event.
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            _notifyToSubscribersDouble.ReceivedWithAnyArgs().Send(null);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        }