IConnectionMultiplexer Redis缓存的NSubstitute单元测试

问题描述

那是我使用Redis的课程:

 public class RateLimitMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConnectionMultiplexer _connectionMultiplexer;
    private readonly Options _options;

    public RateLimitMiddleware(RequestDelegate next,IConnectionMultiplexer connectionMultiplexer,Options options)
    {
        if (next == null)
        {
            throw new ArgumentNullException(nameof(next));
        }

        if (connectionMultiplexer == null)
        {
            throw new ArgumentNullException(nameof(connectionMultiplexer));
        }

        if (options == null)
        {
            throw new ArgumentNullException(nameof(options));
        }

        _next = next;
        _connectionMultiplexer = connectionMultiplexer;
        _options = options;
    }

    public async Task Invoke(HttpContext context)
    {
            var requestsKeyStore = _connectionMultiplexer.GetDatabase();

            var consumerIP = context.Connection.RemoteIpAddress.ToString();

            var consumerKey = $"consumer.throttle#{consumerIP}";

            var requestKeyVal = await requestsKeyStore.HashIncrementAsync(consumerKey,1);

            if (requestKeyVal == 1)
            {
                await requestsKeyStore.KeyExpireAsync(
                    consumerKey,_options.RateLimitKeyExpire,CommandFlags.FireAndForget);
            }
            else if (requestKeyVal > _options.RateLimit)
            {
                context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
                using (var writer = new StreamWriter(context.Response.Body))
                {
                    await writer.WriteAsync("Too many requests.");
                }

                return;
            }

            await _next(context);
    }
}

我正在尝试通过NSubstitute进行测试:

public async Task CheckRateLimit_Should_Fail_On_Too_Much_Requests()
    {
        var context = new DefaultHttpContext();
        context.Connection.RemoteIpAddress = IPAddress.Parse("127.0.0.1");
        var ip = context.Connection.RemoteIpAddress.ToString();
    
        var _connectionMultiplexer = Substitute.For<IConnectionMultiplexer>();
        _connectionMultiplexer.IsConnected.Returns(false);
        var multiplexerDb = Substitute.For<IDatabase>();
        _connectionMultiplexer
            .GetDatabase(Arg.Any<Int32>(),Arg.Any<Object>()).Returns(multiplexerDb);


        var logger = Substitute.For<ILogger<RateLimitMiddleware>>();
        var middleware = new RateLimitMiddleware(
            innerHttpContext => Task.CompletedTask,_connectionMultiplexer,_options,logger
        );

        var startMSecond = DateTime.Now.TimeOfDay.TotalMilliseconds;
        var curMSecond = startMSecond;
        var count = 0;
        while ((curMSecond - startMSecond) < 1000 && count <= _options.RateLimit)
        {
            await middleware.Invoke(context);
            curMSecond = DateTime.Now.TimeOfDay.TotalMilliseconds;
            count++;
        }

        Assert.AreEqual(429,context.Response.StatusCode);
    }

我在测试类中将_options.RateLimit设置为2。因此,在我的while循环中,我每秒发送2个以上的请求,因此应该获得429个响应。

当我没有模拟IConnectionMultiplexer并使用localhost连接到Redis时,它起作用了。现在不是。调试后,我知道在对中间件的每个请求中,调用它都会获得没有任何键的新的clear redis数据库。因此,假设即使使用相同的密钥,每个请求都是新的。 我在做什么错了?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...