我正在模拟与StackExchange.Redis库相关的行为,但不知道如何正确地模拟它使用的密封类。一个具体的例子是在我的调用代码中,我正在做这样的事情:
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,在使用缓存之前,我要检查是否有一个有效的连接。所以在我的测试中,我想用这样的方法来模拟这种行为:
_mockCache = new Mock<IDatabase>();
_mockCache.Setup(cache => cache.Multiplexer.IsConnected).Returns(false);然而,虽然该代码编译得很好,但在运行测试时我得到了这个错误:

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

最终,我想控制这个属性在我的测试中是真是假,那么是否有一种正确的方法来模拟这样的事情呢?
发布于 2015-02-04 16:53:43
在我看来,最好的方法是将您所有的Redis交互都封装在自己的类和接口中。比如CacheHandler : ICacheHandler和ICacheHandler。您的所有代码都只会与ICacheHandler对话。
这样,您就消除了对Redis的硬依赖(您可以随意交换ICacheHandler的实现)。您还可以模拟与缓存层的所有交互,因为它是针对接口编程的。
您不应该直接测试StackExchange.Redis --这不是您编写的代码。
发布于 2017-10-30 11:37:25
在您自己的类中使用接口IConnectionMultiplexer而不是具体的ConnectionMultiplexer类。
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
}
}然后您可以轻松地模拟和测试它:
// 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发布于 2018-08-09 18:31:18
上面的答案中没有包括mockDatabase实例的更详细的设置。我很难找到一个简单的例子,比如模拟IDatabase StringGet方法(例如,处理可选参数、使用RedisKey vs string、使用RedisValue vs string等等),所以我想分享一下。这就是对我有用的东西。
此测试设置:
var expected = "blah";
RedisValue expectedValue = expected;
mockDatabase.Setup(db => db.StringGet(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.Returns(expectedValue);若要影响此测试方法调用返回的内容,请执行以下操作:
var redisValue = _connectionMultiplexer.GetDatabase().StringGet(key);https://stackoverflow.com/questions/28325870
复制相似问题