【问题标题】:How to use Moq to simulate exceptions thrown by the StackExchange.Redis library?如何使用 Moq 模拟 StackExchange.Redis 库抛出的异常?
【发布时间】:2015-02-04 01:51:58
【问题描述】:

我正在处理一个项目,我想使用 StackExchange.Redis 库连接到 Redis 数据库。此外,我想在我们的单元测试中使用 Moq 作为模拟库,但我遇到了一个障碍,我需要一些帮助来解决。

我的具体问题是,我有一个命令/响应架构,并且我正在尝试测试一个缓存“包装器”,该缓存“包装器”在执行实际工作以返回响应之前检查缓存是否可以满足命令。一个重要的考虑因素是缓存故障永远不应该停止处理请求,因此我想模拟 StackExchange.Redis IDatabase 接口的某些故障。但是,我似乎无法弄清楚如何从我的模拟对象中抛出 RedisException。例如,我想只使用下面的代码,但它无法编译,因为该库抛出的异常没有公共构造函数。

    Mock<IDatabase> _mockCache = new Mock<IDatabase>();

    // Simulate a connection exception to validate how the cache layer handles it
    //  THIS DOESN'T COMPILE THOUGH
    //
    _mockCache.Setup(cache => cache.StringGetAsync("a", CommandFlags.None)).Throws<RedisException>();

有没有更好的方法来模拟 StackExchange.Redis 库中的故障?我觉得我在 Moq 或如何针对这个库进行测试时遗漏了一些明显的东西。

【问题讨论】:

    标签: unit-testing moq stackexchange.redis


    【解决方案1】:

    您始终可以使用FormatterServices.GetUninitializedObject 来创建类的实例,而无需运行任何构造函数:

    创建指定对象类型的新实例。

    因为对象的新实例被初始化为零并且没有运行构造函数,所以该对象可能不代表该对象认为有效的状态。当前方法仅应在用户打算立即填充所有字段时用于反序列化。它不会创建未初始化的字符串,因为创建不可变类型的空实例没有任何意义。

    所以您的设置可能如下所示:

    var e = (RedisException)FormatterServices.GetUninitializedObject(typeof(RedisException)); 
    
    Mock<IDatabase> _mockCache = new Mock<IDatabase>();
    _mockCache.Setup(cache => cache.StringGetAsync("a", CommandFlags.None)).Throws(e);
    

    这有点骇人听闻;由于没有运行构造函数,因此您不应依赖 RedisException 实例的有效状态。

    【讨论】:

    • 这可以满足我的需要。我不知道 FormatterServices,谢谢!
    猜你喜欢
    • 2017-07-11
    • 2015-04-04
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 2019-08-30
    • 2019-07-25
    相关资源
    最近更新 更多