首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Moq模拟StackExchange.Redis ConnectionMultiplexer类?

如何使用Moq模拟StackExchange.Redis ConnectionMultiplexer类?
EN

Stack Overflow用户
提问于 2015-02-04 16:02:07
回答 4查看 16.2K关注 0票数 13

我正在模拟与StackExchange.Redis库相关的行为,但不知道如何正确地模拟它使用的密封类。一个具体的例子是在我的调用代码中,我正在做这样的事情:

代码语言:javascript
复制
    var cachable = command as IRedisCacheable;

    if (_cache.Multiplexer.IsConnected == false)
    {
        _logger.Debug("Not using the cache because the connection is not available");

        cacheAvailable = false;
    }
    else if (cachable == null)
    {

其中的关键行是_cache.Multiplexer.IsConnected,在使用缓存之前,我要检查是否有一个有效的连接。所以在我的测试中,我想用这样的方法来模拟这种行为:

代码语言:javascript
复制
    _mockCache = new Mock<IDatabase>();
    _mockCache.Setup(cache => cache.Multiplexer.IsConnected).Returns(false);

然而,虽然该代码编译得很好,但在运行测试时我得到了这个错误:

我还尝试过模拟复用器类本身,并将其提供给我模拟的缓存,但我遇到了一个事实,即复用器类是密封的:

代码语言:javascript
复制
    _mockCache = new Mock<IDatabase>();
    var mockMultiplexer = new Mock<ConnectionMultiplexer>();
    mockMultiplexer.Setup(c => c.IsConnected).Returns(false);
    _mockCache.Setup(cache => cache.Multiplexer).Returns(mockMultiplexer.Object);

导致此错误的...but:

最终,我想控制这个属性在我的测试中是真是假,那么是否有一种正确的方法来模拟这样的事情呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-02-04 16:53:43

在我看来,最好的方法是将您所有的Redis交互都封装在自己的类和接口中。比如CacheHandler : ICacheHandlerICacheHandler。您的所有代码都只会与ICacheHandler对话。

这样,您就消除了对Redis的硬依赖(您可以随意交换ICacheHandler的实现)。您还可以模拟与缓存层的所有交互,因为它是针对接口编程的。

您不应该直接测试StackExchange.Redis --这不是您编写的代码。

票数 15
EN

Stack Overflow用户

发布于 2017-10-30 11:37:25

在您自己的类中使用接口IConnectionMultiplexer而不是具体的ConnectionMultiplexer类。

代码语言:javascript
复制
public interface ICacheable
{
   void DoYourJob();
}

public sealed class RedisCacheHandler : ICacheable
{
    private readonly IConnectionMultiplexer multiplexer;

    public RedisCacheHandler(IConnectionMultiplexer multiplexer)
    {
        this.multiplexer = multiplexer;
    }

    public void DoYourJob() 
    {
        var database = multiplexer.GetDatabase(1);

        // your code        
    }
}

然后您可以轻松地模拟和测试它:

代码语言:javascript
复制
// Arrange
var mockMultiplexer = new Mock<IConnectionMultiplexer>();

mockMultiplexer.Setup(_ => _.IsConnected).Returns(false);

var mockDatabase = new Mock<IDatabase>();

mockMultiplexer
    .Setup(_ => _.GetDatabase(It.IsAny<int>(), It.IsAny<object>()))
    .Returns(mockDatabase.Object);

var cacheHandler = new RedisCacheHandler(mockMultiplexer.Object);

// Act
cacheHandler.DoYourJob();


// Assert
// your tests
票数 17
EN

Stack Overflow用户

发布于 2018-08-09 18:31:18

上面的答案中没有包括mockDatabase实例的更详细的设置。我很难找到一个简单的例子,比如模拟IDatabase StringGet方法(例如,处理可选参数、使用RedisKey vs string、使用RedisValue vs string等等),所以我想分享一下。这就是对我有用的东西。

此测试设置:

代码语言:javascript
复制
var expected = "blah";
RedisValue expectedValue = expected;

mockDatabase.Setup(db => db.StringGet(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.Returns(expectedValue);

若要影响此测试方法调用返回的内容,请执行以下操作:

代码语言:javascript
复制
var redisValue = _connectionMultiplexer.GetDatabase().StringGet(key);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28325870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档