使用MOQ模拟IDatabase接口时Mock<SqlDatabase>赋值报错CS0029如何解决
MOQ模拟IDatabase接口CS0029报错解决方法
报错原因
你写出错的代码Mock<IDatabase> mockDatabase = new Mock<SqlDatabase>();不合法,核心原因是:Mock<SqlDatabase>和Mock<IDatabase>是两个独立的封闭泛型类型,不存在继承关系,哪怕SqlDatabase实现了IDatabase接口,也不能直接将Mock<SqlDatabase>实例赋值给Mock<IDatabase>类型的变量。
正确解决方案
根据你的使用场景选择对应写法即可:
- 场景1:仅需要模拟
IDatabase接口行为,不需要用到SqlDatabase的原有实现逻辑
直接用IDatabase作为泛型参数初始化Mock实例即可,你当前贴出的单元测试代码里的写法本身就是正确的,修正之前写错的右侧泛型参数即可解决报错:// 正确写法,直接针对接口创建Mock Mock<IDatabase> mockDatabase = new Mock<IDatabase>(); // 后续测试逻辑无需调整 var sut = new ToneAnalyzerEngine(mockDatabase.Object); var v = sut.Analyze(comment, MockToneAnalyzerResultSadness()); mockDatabase.Verify(x => x.Save(It.IsAny<AnalyzerModel>()), Times.Once); mockDatabase.VerifyNoOtherCalls(); - 场景2:需要部分模拟
SqlDatabase,即保留SqlDatabase的部分原有逻辑,仅重写部分方法
可以先初始化SqlDatabase的Mock,再通过As<T>()方法转成IDatabase类型的Mock实例:Mock<SqlDatabase> mockSqlDb = new Mock<SqlDatabase>(); // 转换为IDatabase类型的Mock Mock<IDatabase> mockDatabase = mockSqlDb.As<IDatabase>(); // 后续Setup、Verify等操作和直接模拟接口完全一致
额外注意事项
你最开始贴出的IDatabase接口定义中Save是无参数方法,但业务代码里调用的是带AnalyzerModel参数的Save方法,二者签名不一致,如果是实际代码的笔误请先修正接口定义,避免后续运行时报错。
内容的提问来源于stack exchange,提问作者TriCron
相关产品推荐
相关产品推荐

