public async Task RedisValidationCacheDataRepository_AddValidNonPresentKeyAndValidValue_ShouldWork()
        {
            // Arrange
            string key = "some key";

            var value = new ValidationCacheEntity();

            var listMock = new Mock <IRedisList>();

            var clientMock = new Mock <IRedisClient>();

            clientMock
            .Setup(c => c.Lists[It.IsAny <string>()])
            .Returns(listMock.Object);

            var clientProviderMock = new Mock <IRedisClientProvider>();

            clientProviderMock
            .Setup(p => p.Create())
            .Returns(clientMock.Object);

            var repository = new RedisValidationCacheDataRepository(clientProviderMock.Object);

            // Act
            var result = await repository.Add(key, value);

            // Asset
            Assert.That(result, Is.EqualTo(true));

            clientProviderMock.Verify(p => p.Create(), Times.Once);
            clientMock.Verify(c => c.Lists[key], Times.Once);
            clientMock.Verify(c => c.Dispose(), Times.Once);
            listMock.Verify(l => l.Add(It.IsAny <string>()), Times.Once);
        }
        public async Task RedisValidationCacheDataRepository_AddMultipleValuesInTheSameKeyAndRemoveThem_ShouldWork()
        {
            // Arrange
            const int NumberOfItems  = 100;
            var       clientProvider = new RedisClientProvider();
            var       repository     = new RedisValidationCacheDataRepository(clientProvider);
            var       key            = Guid.NewGuid().ToString();

            var values = new List <IValidationCacheEntity>(NumberOfItems);

            // Act: Clean-up database
            await repository.Remove(key);

            await repository.SaveChangesAsync();

            // Act: Add
            for (int i = 0; i < NumberOfItems; ++i)
            {
                var now     = DateTime.Now + TimeSpan.FromHours(i);
                var content = $"{key} {i} {now.ToLongTimeString()}";
                var value   = new ValidationCacheEntity
                {
                    Content    = content,
                    LastUpdate = now,
                    Status     = (ValidationStatus)(i % 3)
                };

                values.Add(value);
                await repository.Add(key, value);
            }

            values.TrimExcess();
            await repository.SaveChangesAsync();

            // Act: Get
            var valuesFromDb = repository.GetAll(key).ToList();

            // Assert: Get
            Assert.AreEqual(NumberOfItems, values.Count);
            Assert.AreEqual(NumberOfItems, valuesFromDb.Count);

            foreach (var value in values)
            {
                var valueFromDb = valuesFromDb.Single(v => v.Content == value.Content);
                Assert.IsNotNull(valueFromDb);

                Assert.AreEqual(value.Status, valueFromDb.Status);
                Assert.AreEqual(value.LastUpdate.ToLongTimeString(), valueFromDb.LastUpdate.ToLongTimeString());
                Assert.AreEqual(value.Content, valueFromDb.Content);
            }

            // Act: Remove
            await repository.Remove(key);

            Assert.That(async() => await repository.SaveChangesAsync(), Is.EqualTo(0L).After(2000));

            // Assert: Remove
            Assert.AreEqual(0, repository.GetAll(key).ToList().Count, "All values in the list should be removed.");
        }
        public void RedisValidationCacheDataRepository_AddNewValidKeyValuePairAndThenGetAllAndRemoveIt_ShouldWork()
        {
            // Arrange
            var clientProvider = new RedisClientProvider();
            var repository     = new RedisValidationCacheDataRepository(clientProvider);
            var key            = Guid.NewGuid().ToString();
            var value          = new ValidationCacheEntity
            {
                Content    = Guid.NewGuid().ToString(),
                LastUpdate = DateTime.UtcNow,
                Status     = ValidationStatus.Invalid
            };

            // Act: Add
            var added = repository.Add(key, value);

            // Assert: Add
            Assert.That(async() => await added, Is.EqualTo(true));

            // Act + Assert: SaveChanges
            Assert.That(async() => await repository.SaveChangesAsync(), Is.EqualTo(0L).After(2000));

            // Act: Get
            var valuesFromDb = repository.GetAll(key);
            var valueFromDb  = valuesFromDb.Single();

            // Assert: Get
            Assert.AreEqual(1, valuesFromDb.Count());

            Assert.IsNotNull(valueFromDb);

            Assert.AreEqual(value.Status, valueFromDb.Status);
            Assert.AreEqual(value.Content, valueFromDb.Content);
            Assert.AreEqual(value.LastUpdate.ToLongDateString(), valueFromDb.LastUpdate.ToLongDateString());
            Assert.AreEqual(value.LastUpdate.ToLongTimeString(), valueFromDb.LastUpdate.ToLongTimeString());

            // Act: Remove value
            var removedValue = repository.Remove(key, value);

            // Assert: Remove value
            Assert.That(async() => await removedValue, Is.EqualTo(true));

            // Act: Remove
            var removed = repository.Remove(key);

            // Assert: Remove
            Assert.That(async() => await removed, Is.EqualTo(true));

            // Act + Assert: SaveChanges
            // Expected internal catch of "ServiceStack.Redis.RedisResponseException : Background save already in progress"
            Assert.That(async() => await repository.SaveChangesAsync(), Is.EqualTo(1L));
        }
        public async Task RedisValidationCacheDataRepository_GetKeys_ShouldWork()
        {
            // Arrange
            const int NumberOfKeys = 10;
            var       listOfKeys   = Enumerable.Range(0, NumberOfKeys)
                                     .Select(i => Guid.NewGuid().ToString() + i)
                                     .ToList();

            var clientProvider = new RedisClientProvider();
            var repository     = new RedisValidationCacheDataRepository(clientProvider);

            var value = new ValidationCacheEntity
            {
                Content    = Guid.NewGuid().ToString(),
                LastUpdate = DateTime.UtcNow,
                Status     = ValidationStatus.Valid
            };

            // Act: Add
            foreach (var key in listOfKeys)
            {
                await repository.Add(key, value);
            }

            // Act: Get Keys
            var keysAfterAdd = repository.Keys.ToList();

            // Assert: Get Keys
            Assert.AreEqual(NumberOfKeys, keysAfterAdd.Count, $"Number of keys after add should be {NumberOfKeys}.");

            foreach (var key in listOfKeys)
            {
                var keyFromDb = keysAfterAdd.Single(k => k == key);
                Assert.AreEqual(key, keyFromDb);
            }

            // Act: Remove
            foreach (var key in listOfKeys)
            {
                await repository.Remove(key);
            }

            // Act: Get Keys
            var keysAfterRemove = repository.Keys.ToList();

            // Assert: Get Keys
            Assert.AreEqual(0, keysAfterRemove.Count, $"Number of keys after insert should be 0.");
        }
        public async Task RedisValidationCacheDataRepository_AddAndRemoveKeyValuePair_ShouldWork()
        {
            // Arrange
            var clientProvider = new RedisClientProvider();
            var repository     = new RedisValidationCacheDataRepository(clientProvider);
            var key            = Guid.NewGuid().ToString();

            var now   = DateTime.Now;
            var value = new ValidationCacheEntity
            {
                Content    = $"{key} {now.ToLongTimeString()}",
                LastUpdate = now,
                Status     = ValidationStatus.Valid
            };

            // Act: Clean-up database
            await repository.Remove(key);

            await repository.SaveChangesAsync();

            // Act: Add
            await repository.Add(key, value);

            await repository.SaveChangesAsync();

            // Act + Assert: Retrieve data
            var valuesFromDb = repository.GetAll(key).ToList();

            Assert.AreEqual(1, valuesFromDb.Count);

            var valueFromDb = valuesFromDb.Single();

            Assert.AreEqual(ValidationStatus.Valid, valueFromDb.Status);
            Assert.AreEqual(now.ToLongTimeString(), valueFromDb.LastUpdate.ToLongTimeString());
            Assert.AreEqual(value.Content, valueFromDb.Content);

            // Act: Remove
            await repository.Remove(key);

            Assert.That(async() => await repository.SaveChangesAsync(), Is.EqualTo(0L).After(2000));

            // Assert: Remove
            Assert.AreEqual(0, repository.GetAll(key).ToList().Count, "All values in the list should be removed.");
        }