Пример #1
0
        public void An_item_is_cached_with_the_default_key()
        {
            var item = new Item();
            var key  = item.Id;

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns(item);

            var cache = new MKCache <Item>();

            var foundItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, cachedItem);

            var _ = cache.GetOrCreate(item.Name, factoryMock.Object, Expiration);

            // Delegate invoked a second time, because the item was not found
            factoryMock.Verify(factory => factory(), Times.Exactly(2));
        }
Пример #2
0
 public CacheWithKid(
     MemoryCache cache,
     MKCache <T> .KeyIdentifier keyIdentifier)
 {
     Cache         = cache;
     KeyIdentifier = keyIdentifier;
 }
Пример #3
0
        public void An_item_is_cached_with_multiple_keys()
        {
            var item = new Item();
            var key  = item.Id;

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns(item);

            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            var foundItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, cachedItem);

            var cachedItemWithDifferentKey = cache.GetOrCreate(item.Name, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, cachedItemWithDifferentKey);
        }
Пример #4
0
        public async Task Default_key_cache_can_be_cleared()
        {
            var item = new Item();
            var key  = item.Id;

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(Task.FromResult(item));

            var cache = new MKCache <Item>();

            var foundItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, cachedItem);

            cache.Clear();

            var _ = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Exactly(2));
        }
Пример #5
0
        public async Task Cache_item_expires_async()
        {
            var cache = new MKCache <Item>();

            var item = new Item();

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(Task.FromResult(item));

            var expirySpan = TimeSpan.FromSeconds(1);

            var foundItem = await cache.GetOrCreateAsync(item.Id, asyncFactoryMock.Object, expirySpan);

            asyncFactoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = await cache.GetOrCreateAsync(item.Id, () => Task.FromResult(new Item()), expirySpan);

            Assert.Same(item, cachedItem);

            await Task.Delay(expirySpan * 3);

            var newItem = await cache.GetOrCreateAsync(item.Id, asyncFactoryMock.Object, expirySpan);

            asyncFactoryMock.Verify(factory => factory(), Times.Exactly(2));
        }
Пример #6
0
        public async Task An_item_is_cached_with_a_single_key_async()
        {
            var item = new Item();

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(Task.FromResult(item));

            var cache = new MKCache <Item>(
                x => x.Name /* Name property is the key */);

            _ = await cache.GetOrCreateAsync(item.Id, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);

            var cachedItem = await cache.GetOrCreateAsync(item.Name, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, cachedItem);

            _ = await cache.GetOrCreateAsync(item.Id, asyncFactoryMock.Object, Expiration);

            // Delegate invoked a second time, because the item was not found using its Id
            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Exactly(2));
        }
Пример #7
0
        public void Cache_can_be_cleared()
        {
            var item = new Item();
            var key  = item.Id;

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns(item);

            var cache = new MKCache <Item>();

            var foundItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, cachedItem);

            cache.Clear();

            var newlyCachedItem = cache.GetOrCreate(key, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Exactly(2));
            Assert.Same(item, newlyCachedItem);
        }
Пример #8
0
        public async Task Null_key_from_identifier_does_not_throw_and_value_does_not_get_cached_async()
        {
            var cache = new MKCache <Item>(
                x => x.Name /* The Name is the key */);

            var item = new Item(name: null !);

            var factoryMock = new Mock <Func <Task <Item> > >();

            factoryMock.Setup(factory => factory()).Returns(Task.FromResult(item));

            var foundItem = await cache.GetOrCreateAsync(item.Id, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            foundItem = await cache.GetOrCreateAsync("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Exactly(2));
            Assert.Same(item, foundItem);

            foundItem = await cache.GetOrCreateAsync("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Exactly(3));
            Assert.Same(item, foundItem);
        }
Пример #9
0
 public void Deconstruct(
     out MemoryCache cache,
     out MKCache <T> .KeyIdentifier keyIdentifier)
 {
     cache         = Cache;
     keyIdentifier = KeyIdentifier;
 }
Пример #10
0
        public async Task An_item_is_cached_with_multiple_keys_async()
        {
            var item = new Item();
            var key  = item.Id;

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(Task.FromResult(item));

            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            var foundItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, cachedItem);

            var cachedItemWithDifferentKey = await cache.GetOrCreateAsync(item.Name, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, cachedItemWithDifferentKey);
        }
Пример #11
0
        public async Task An_item_is_cached_with_the_default_key_async()
        {
            var item = new Item();
            var key  = item.Id;

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(Task.FromResult(item));

            var cache = new MKCache <Item>();

            var foundItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = await cache.GetOrCreateAsync(key, asyncFactoryMock.Object, Expiration);

            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Once);
            Assert.Same(item, cachedItem);

            var _ = await cache.GetOrCreateAsync(item.Name, asyncFactoryMock.Object, Expiration);

            // Delegate invoked a second time, because the item was not found
            asyncFactoryMock.Verify(asyncFactory => asyncFactory(), Times.Exactly(2));
        }
Пример #12
0
        public void Removing_missing_item_does_not_throw()
        {
            var cache = new MKCache <Item>();

            Assert.Equal(0, cache.Count);

            var missing = cache.Remove("foo");

            Assert.Null(missing);
        }
Пример #13
0
        public void Can_set_item()
        {
            var cache = new MKCache <Item>();
            var key   = "foo";

            var existingItem = cache.Get(key);

            Assert.Null(existingItem);

            cache.Set(key, new Item(), Expiration);

            existingItem = cache.Get(key);
            Assert.NotNull(existingItem);
        }
        public async Task Running_async_fetchers_are_reused()
        {
            var item = new Item();

            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(() => Task.Run(async() =>
            {
                // A time long enough for the test to request n concurrent async factories invocations
                await Task.Delay(TimeSpan.FromSeconds(2));
                return(item);
            }));

            var cache = new MKCache <Item>
            {
                ReuseRunningAsyncFetchers = true
            };

            var foundItemTask = cache.GetOrCreateAsync("any", asyncFactoryMock.Object, Expiration);

            // Simulate concurrent request for the same object (same key), while the item is not yet been cached.
            var concurrentFinders = new List <Task <Item> >();
            var n = 100;

            for (int i = 0; i < n; i++)
            {
                concurrentFinders.Add(cache.GetOrCreateAsync("any", asyncFactoryMock.Object, Expiration));
            }

            var foundItem = await foundItemTask;

            // The delegate is invoked only once
            asyncFactoryMock.Verify(asyncFinder => asyncFinder(), Times.Once);

            // The reused and completed task gets mapped into another task for each call (by the cache awaiting it),
            // therefore we might still be needing to await them to complete.
            await Task.WhenAll(concurrentFinders);

            // Even if the Id gets created new each time, the same result has been returned.
            concurrentFinders.ForEach(t => Assert.Equal(t.Result.Id, foundItem.Id));

            // After the async fetcher has completed, the item is stored in cache
            // so the delegate still won't be invoked (but for a different reason).

            var cachedItem = await cache.GetOrCreateAsync("any", asyncFactoryMock.Object, Expiration);

            Assert.Same(item, cachedItem);
            asyncFactoryMock.Verify(asyncFinder => asyncFinder(), Times.Once);
        }
Пример #15
0
        public void Can_inspect_items_count()
        {
            var cache = new MKCache <int>();

            Assert.Equal(0, cache.Count);

            cache.GetOrCreate("1", () => 1, Expiration);
            Assert.Equal(1, cache.Count);

            cache.GetOrCreate("2", () => 2, Expiration);
            Assert.Equal(2, cache.Count);

            cache.Clear();
            Assert.Equal(0, cache.Count);
        }
Пример #16
0
        public void Can_be_disposed()
        {
            var cache = new MKCache <Item>();

            var item = cache.GetOrCreate("1", () => new Item(), Expiration);

            cache.Dispose();

            // Dispose is not Clear.
            Assert.Equal(1, cache.Count);

            // Disposed cache cannot be used anymore.
            Assert.Throws <ObjectDisposedException>(() =>
                                                    cache.GetOrCreate("1", () => new Item(), Expiration));
        }
Пример #17
0
        public void Null_value_does_not_throw_and_does_not_get_cached()
        {
            var cache = new MKCache <Item>();

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns((null as Item) !);

            var nullItem = cache.GetOrCreate("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Null(nullItem);

            nullItem = cache.GetOrCreate("any", factoryMock.Object, Expiration);
            factoryMock.Verify(factory => factory(), Times.Exactly(2));
            Assert.Null(nullItem);
        }
Пример #18
0
        public void Item_can_be_removed()
        {
            var cache = new MKCache <Item>();
            var key   = "foo";

            cache.Set(key, new Item(), Expiration);

            var existingItem = cache.Get(key);

            Assert.NotNull(existingItem);

            existingItem = cache.Remove(key);
            Assert.NotNull(existingItem);

            existingItem = cache.Get(key);
            Assert.Null(existingItem);
        }
Пример #19
0
        public void Can_set_item()
        {
            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            var item = new Item();

            var existingItem = cache.Get(item.Id);

            Assert.Null(existingItem);

            cache.Set("", item, Expiration);

            existingItem = cache.Get(item.Id);
            Assert.NotNull(existingItem);
        }
Пример #20
0
        public void Can_inspect_items_count()
        {
            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            Assert.Equal(0, cache.Count);

            cache.GetOrCreate("1", () => new Item(), Expiration);
            Assert.Equal(1, cache.Count);

            cache.GetOrCreate("name", () => new Item(), Expiration);
            Assert.Equal(2, cache.Count);

            cache.Clear();
            Assert.Equal(0, cache.Count);
        }
Пример #21
0
        public async Task Null_value_does_not_throw_and_does_not_get_cached_async()
        {
            var cache = new MKCache <Item>();

            var factoryMock = new Mock <Func <Task <Item> > >();

            factoryMock.Setup(factory => factory()).Returns(Task.FromResult(null as Item) !);

            var nullItem = await cache.GetOrCreateAsync("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Null(nullItem);

            nullItem = await cache.GetOrCreateAsync("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Exactly(2));
            Assert.Null(nullItem);
        }
Пример #22
0
        public async Task Single_key_item_expires()
        {
            var cache = new MKCache <Item>();
            var key   = "foo";

            var existingItem = cache.Get(key);

            Assert.Null(existingItem);

            cache.Set(key, new Item(), TimeSpan.FromMilliseconds(100));

            existingItem = cache.Get(key);
            Assert.NotNull(existingItem);

            await Task.Delay(3000);

            existingItem = cache.Get(key);
            Assert.Null(existingItem);
        }
Пример #23
0
        public void Item_can_be_removed()
        {
            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            var item = new Item();

            cache.Set(item.Id, item, Expiration);

            var existingItem = cache.Get(item.Id);

            Assert.NotNull(existingItem);

            existingItem = cache.Remove(item.Id);
            Assert.NotNull(existingItem);

            existingItem = cache.Get(item.Id);
            Assert.Null(existingItem);
        }
Пример #24
0
        public async Task Multi_key_item_expires()
        {
            var cache = new MKCache <Item>(
                x => x.Id,
                x => x.Name);

            var item = new Item();

            var existingItem = cache.Get(item.Id);

            Assert.Null(existingItem);

            cache.Set("", item, TimeSpan.FromMilliseconds(100));

            existingItem = cache.Get(item.Id);
            Assert.NotNull(existingItem);

            await Task.Delay(3000);

            existingItem = cache.Get(item.Id);
            Assert.Null(existingItem);
        }
Пример #25
0
        public void An_item_is_cached_with_a_single_key()
        {
            var item = new Item();

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns(item);

            var cache = new MKCache <Item>(
                x => x.Name /* Name property is the key */);

            _ = cache.GetOrCreate(item.Id, factoryMock.Object, Expiration);
            factoryMock.Verify(factory => factory(), Times.Once);

            var cachedItem = cache.GetOrCreate(item.Name, factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, cachedItem);

            _ = cache.GetOrCreate(item.Id, factoryMock.Object, Expiration);
            // Delegate invoked a second time, because the item was not found using its Id
            factoryMock.Verify(factory => factory(), Times.Exactly(2));
        }
Пример #26
0
        public void Items_can_be_retrieved_from_the_cache()
        {
            var item = new Item();

            var factoryMock = new Mock <Func <Item> >();

            factoryMock.Setup(factory => factory()).Returns(item);

            var cache = new MKCache <Item>();

            var nullItem = cache.Get("any");

            Assert.Null(nullItem);

            var foundItem = cache.GetOrCreate("any", factoryMock.Object, Expiration);

            factoryMock.Verify(factory => factory(), Times.Once);
            Assert.Same(item, foundItem);

            var cachedItem = cache.Get("any");

            Assert.Same(item, cachedItem);
        }
        public async Task Running_async_fetchers_are_not_reused_by_configuration()
        {
            var asyncFactoryMock = new Mock <Func <Task <Item> > >();

            asyncFactoryMock.Setup(asyncFactory => asyncFactory()).Returns(() => Task.Run(async() =>
            {
                // A time long enough for the test to request n concurrent async factories invocations
                await Task.Delay(TimeSpan.FromSeconds(2));
                return(new Item());
            }));

            var cache = new MKCache <Item>
            {
                ReuseRunningAsyncFetchers = false
            };

            var foundItemTask = cache.GetOrCreateAsync("any", asyncFactoryMock.Object, Expiration);

            // Simulate concurrent request for the same object (same key), while the item is not yet been cached.
            var concurrentFinders = new List <Task <Item> >();
            var n = 100;

            for (int i = 0; i < n; i++)
            {
                concurrentFinders.Add(cache.GetOrCreateAsync("any", asyncFactoryMock.Object, Expiration));
            }

            var foundItem = await foundItemTask;
            await Task.WhenAll(concurrentFinders);

            // Tasks have not been reused, therefore each item is different.
            concurrentFinders.ForEach(t => Assert.NotEqual(t.Result.Id, foundItem.Id));

            // Ensure that all the delegates have been invoked.
            asyncFactoryMock.Verify(asyncFinder => asyncFinder(), Times.Exactly(n + 1));
        }