In this lesson, you will learn how to verify that your application correctly interacts with a distributed cache like Redis without relying on fragile, mocked dependencies.
The Problem with Mocking IDistributedCache
When testing services that use IDistributedCache, many developers make the mistake of mocking the interface. By doing so, you are simply testing that your code calls a mock—you aren’t verifying that the data is correctly serialized, that TTL (Time-To-Live) settings are respected, or that cache collisions are handled properly. To ensure true software quality, we must move beyond unit-level mocks and test against real caching infrastructure.
Testing with Testcontainers
Since we previously established that integration testing should utilize real infrastructure, we use Testcontainers to spin up a ephemeral Redis instance. This ensures that your integration tests run in an environment identical to your production cache.
When writing your WebApplicationFactory setup, you can override the cache configuration to point to your containerized Redis instance:
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration((context, config) =>
{
config.AddInMemoryCollection(new Dictionary<string, string> {
{"ConnectionStrings:Redis", _redisContainer.GetConnectionString()}
});
});
}
Verifying Cache Interaction
To verify your distributed cache interaction, perform a "Write-Read-Assert" cycle.
- Trigger the Action: Perform an API call or service method that you expect to populate the cache.
- Access the Infrastructure: Connect directly to the Testcontainers Redis instance in your test to verify the raw key-value pair exists.
- Assert Serialization: Check that the object was serialized into the format your application expects (e.g., JSON).
[Fact]
public async Task GetUser_CachesResultInRedis()
{
// Arrange: Clear Redis or use a unique key
var key = "user:123";
// Act: Call the API
await _client.GetAsync("/api/users/123");
// Assert: Check the real Redis instance
var cachedData = await _redisDatabase.StringGetAsync(key);
Assert.NotNull(cachedData);
Assert.Contains("John Doe", cachedData);
}
By inspecting the cache layer directly, you prove that your application isn't just "calling a method," but is actually storing state in a way that other distributed instances could retrieve.
Key Takeaway: Never mock IDistributedCache; instead, use Testcontainers to verify that your serialization, keys, and TTL settings function correctly against a real Redis instance.