user2503078
user2503078

Reputation: 807

Unit Test and IDistributedCache using azure redis

I have a working implementation of Azure Redis and .Net Core 2 using code very similar to what's described in this article

My question is, how do you instantiate an instance of the cache from a unit test class? I've looked through a number of resources and found nothing.

I need to be able to create an instance to instantiate a class such as

    public CacheManager(IDataManager dataservices, IDistributedCache cache)
    {
        _cache = cache;
        _dataservices = dataservices;
    }

The code in startup.cs uses ConfigureServices

            //Configure Redis Cache
        var redisconnection = Configuration.GetConnectionString("Redis");
        services.AddDistributedRedisCache(o => { o.Configuration = redisconnection; });

Maybe I need to add a package to the unit test project? How is this done?

Upvotes: 15

Views: 15512

Answers (4)

z zandi
z zandi

Reputation: 21

i needed DistributedCache for test a service so i wrote these code:

private IDistributedCache BuildDistributedCash()
{
    var opt = Options.Create(new MemoryDistributedCacheOptions());
    return new MemoryDistributedCache(opt);
}

[Fact]
public async Task CheckStatusTest()
{
    var buildDistributedCash = BuildDistributedCash();
    var authService = new AuthService(buildDistributedCash);
    var userName = "[email protected]";

    bool result = await authService.CheckStatus(userName);

    Assert.True(result); 
}

Upvotes: 1

Sau001
Sau001

Reputation: 1664

I have used the Microsoft.Extensions.Caching.Distributed.MemoryDistributedCache class for unit testing. This is an in-memory implementation of IDistributedCache.

Here is a snippet of my unit testing code.

        [TestMethod]
        public void ExampleTestMethod()
        {
            var expectedData = new byte[] { 100, 200 };

            var opts = Options.Create<MemoryDistributedCacheOptions>(new MemoryDistributedCacheOptions());
            IDistributedCache cache1 = new MemoryDistributedCache(opts);
            cache1.Set("key1", expectedData);
            var cachedData = cache1.Get("key1");

            Assert.AreEqual(expectedData, cachedData);

           //Use the variable cache as an input to any class which expects IDistributedCache
        }

In my example, I am on .NET Core 3.1 and the relevant NUGET packages are

    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.4" />

Upvotes: 24

peyman gilmour
peyman gilmour

Reputation: 1218

This how i managed to do that in .net core 2.0 and 3.1. You need to use MemoryDistributedCache. And pass it through your service constructor. Your service in a real word uses IDistributedCache by depedency injection. MemoryDistributedCache also implements IDistributedCache.

var mockedCacheSettings = new Mock<IOptions<CacheSettings>>();

        var options = new OptionsWrapper<MemoryDistributedCacheOptions>(new MemoryDistributedCacheOptions());
        _memoryDistributedCache = new MemoryDistributedCache(options);
        _distributedCacheService = new DistributedCacheService(_memoryDistributedCache, mockedCacheSettings.Object, NullLogger<DistributedCacheService>.Instance);

Upvotes: 1

Nkosi
Nkosi

Reputation: 246998

You could just mock the interfaces to behave as needed for the isolated unit test.

public void Test_CacheManager() {
    //Arrange
    IDataManager dataservices = new Mock<IDataManager>(); 
    IDistributedCache cache = new Mock<IDistributedCache>();
    var subject = new CacheManager(dataservices.Object, cache.Object);

    //Setup the mocks to behave as expected.

    //Act
    //...call the method under test

    //Assert
    //...assert the expected behavior
}

The above example uses Moq in order to demonstrate how to mock instances of the dependencies of the class under test.

Reference Moq Quickstart to get a better understanding of how to use the mocking library.

If you are connecting to an actual redis connection then this will no longer be a unit test but an integration test, which would require a completely different approach.

public void Test_CacheManager() {
    //Arrange

    IDataManager dataservices = new Mock<IDataManager>(); 
     //Setup the mocks to behave as expected.

    //Configure Redis Cache
    var services = new ServiceCollection();
    var redisconnection = "...";
    services.AddDistributedRedisCache(o => { o.Configuration = redisconnection; });
    var provider = services.BuildServiceProvider();
    IDistributedCache cache = provider.GetService<IDistributedCache>();

    var subject = new CacheManager(dataservices.Object, cache);

    //Act
    //...call the method under test

    //Assert
    //...assert the expected behavior
}

Upvotes: 3

Related Questions