public async Task SaveEvents_inserts_Correlation_entity_correctly()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created       = new FakeUserCreated();
            var correlationId = Guid.NewGuid();

            created.Raise(userId);
            DateTime now = DateTime.UtcNow;

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            await sut.SaveEvents <FakeUser>(new[] { created }, correlationId : correlationId);

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                Correlation correlation = await db
                                          .Correlations
                                          .Where(
                    c =>
                    c.AggregateType == typeof(FakeUser).FullName &&
                    c.AggregateId == userId &&
                    c.CorrelationId == correlationId)
                                          .SingleOrDefaultAsync();

                correlation.Should().NotBeNull();
                correlation.HandledAt.Should().BeCloseTo(now, precision: 100);
            }
        }
        public async Task SaveEvents_does_not_insert_UniqueIndexedProperty_if_property_value_is_null()
        {
            // Arrange
            var userId = Guid.NewGuid();

            var created = new FakeUserCreated {
                Username = null
            };

            created.Raise(userId);

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            await sut.SaveEvents <FakeUser>(new DomainEvent[] { created });

            // Assert
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                UniqueIndexedProperty actual = await db
                                               .UniqueIndexedProperties
                                               .Where(
                    p =>
                    p.AggregateType == typeof(FakeUser).FullName &&
                    p.PropertyName == nameof(FakeUserCreated.Username) &&
                    p.PropertyValue == created.Username)
                                               .SingleOrDefaultAsync();

                actual.Should().BeNull();
            }
        }
        public async Task FindIdByUniqueIndexedProperty_returns_aggregate_id_if_property_found()
        {
            var userId  = Guid.NewGuid();
            var created = new FakeUserCreated();

            created.Raise(userId);
            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());
            await sut.SaveEvents <FakeUser>(new[] { created });

            Guid?actual = await sut.FindIdByUniqueIndexedProperty <FakeUser>("Username", created.Username);

            actual.Should().Be(userId);
        }
        public void SaveEvents_fails_if_events_contains_null()
        {
            // Arrange
            var userId  = Guid.NewGuid();
            var created = new FakeUserCreated();

            created.Raise(userId);
            var events = new DomainEvent[] { created, null };

            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            // Act
            Func <Task> action = () => sut.SaveEvents <FakeUser>(events);

            // Assert
            action.ShouldThrow <ArgumentException>().Where(x => x.ParamName == "events");
        }
        public async Task SaveEvents_fails_if_unique_indexed_property_duplicate()
        {
            // Arrange
            var sut = new SqlEventStore(
                () => new FakeEventStoreDbContext(_dbContextOptions),
                new JsonMessageSerializer());

            string duplicateUserName = Guid.NewGuid().ToString();

            var macId      = Guid.NewGuid();
            var macCreated = new FakeUserCreated {
                Username = duplicateUserName
            };

            macCreated.Raise(macId);
            await sut.SaveEvents <FakeUser>(new[] { macCreated });

            // Act
            var toshId      = Guid.NewGuid();
            var toshCreated = new FakeUserCreated {
                Username = duplicateUserName
            };

            toshCreated.Raise(toshId);
            Func <Task> action = () => sut.SaveEvents <FakeUser>(new[] { toshCreated });

            // Assert
            action.ShouldThrow <Exception>();
            using (var db = new FakeEventStoreDbContext(_dbContextOptions))
            {
                IQueryable <PersistentEvent> query =
                    from e in db.PersistentEvents
                    where e.AggregateId == toshId
                    select e;
                (await query.AnyAsync()).Should().BeFalse();
            }
        }