1. Install NuGet package
dotnet add package StackExchange.Redis
2. Configuration connection string
Here, I config it in appsettings.json
"ConnectionStrings": {
"Redis": "localhost:6379"
}
3. Configure connectiong string in Program.cs
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{
var redisCon = builder.Configuration.GetConnectionString("Redis")!;
var configuration = ConfigurationOptions.Parse(redisCon, true);
configuration.ResolveDns = true;
return ConnectionMultiplexer.Connect(configuration);
});
4. DI IConnectionMultiplexer to service
public class BasicJwtTokenValidationMiddleware
{
private readonly RequestDelegate _next;
private readonly List<string> _authWhiteList;
private readonly IConnectionMultiplexer _redis;
public BasicJwtTokenValidationMiddleware(RequestDelegate next,
IOptions<AuthenticationOptions> authOptions,
IConnectionMultiplexer redis)
{
_next = next;
_authWhiteList = authOptions.Value.AuthWhiteList;
_redis = redis;
}
public Task Invoke(HttpContext context)
{
// *****
var redisVersion = await _redis.GetDatabase().StringGetAsync($"jwt:version:{userPublicId}");
// ***
}
}
5. How to mock it in unit test (use AutoFixture + Moq)
[Theory, AutoMoqData]
public async Task IsValidVersionAsync_ReturnsTrue_WhenVersionMatches(
[Frozen] Mock<IConnectionMultiplexer> redisMock,
[Frozen] Mock<IDatabase> dbMock)
{
// Arrange
var userId = "user-123";
var version = "3";
dbMock.Setup(db => db.StringGetAsync($"jwt:version:{userId}", It.IsAny<CommandFlags>()))
.ReturnsAsync(version);
redisMock.Setup(r => r.GetDatabase(It.IsAny<int>(), null))
.Returns(dbMock.Object);
}
Why do we mock GetDatabase with parameters even though we call it without parameters in code?
Answer: Because GetDatabase uses default parameter values in C#;
Method definition of GetDatabase:
IDatabase GetDatabase(int db = -1, object? asyncState = null);
So, if we mock with our parameters like:redisMock.Setup(c => c.GetDatabase())
. It won't match the actual call to GetDatabase(-1, null)
Top comments (0)