Sam*_*rie 8 .net c# unit-testing moq stackexchange.redis
我正在努力模拟与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)
{
Run Code Online (Sandbox Code Playgroud)
其中的关键行是_cache.Multiplexer.IsConnected我正在检查以确保在使用缓存之前我有一个有效的连接.所以在我的测试中,我想用这样的方式模拟这种行为:
_mockCache = new Mock<IDatabase>();
_mockCache.Setup(cache => cache.Multiplexer.IsConnected).Returns(false);
Run Code Online (Sandbox Code Playgroud)
但是,虽然该代码编译得很好,但在运行测试时出现此错误:

我也试过模拟多路复用器本身,并将其提供给我的模拟缓存,但我遇到了多路复用器类被密封的事实:
_mockCache = new Mock<IDatabase>();
var mockMultiplexer = new Mock<ConnectionMultiplexer>();
mockMultiplexer.Setup(c => c.IsConnected).Returns(false);
_mockCache.Setup(cache => cache.Multiplexer).Returns(mockMultiplexer.Object);
Run Code Online (Sandbox Code Playgroud)
...但是会导致此错误:

最终我想在我的测试中控制该属性是真还是假,所以有没有正确的方法来模拟这样的东西?
Han*_*ney 12
在我看来,最好的方法是将你所有的Redis交互包装在你自己的类和接口中.像CacheHandler : ICacheHandler和的东西ICacheHandler.你的所有代码都只会说话ICacheHandler.
这样,您就消除了对Redis的强烈依赖(您可以根据需要更换实现ICacheHandler).您还可以模拟与缓存层的所有交互,因为它是针对接口编程的.
你不应该StackExchange.Redis直接测试- 这不是你写的代码.
使用接口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
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以轻松地模拟和测试它:
// 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
Run Code Online (Sandbox Code Playgroud)