使用Moq Mock继承IRepository的仓储类触发InvalidCastException如何解决
你遇到的转换错误本质是类型不匹配:通过Mock.Of<IRepository<SomeReadModel, SomeDto, SomeFilter>>()生成的是仅实现了IRepository接口的代理对象,该代理类并没有继承SomethingRepository,属于父接口实例向下强转子类实现类的非法操作,自然会抛出InvalidCastException。
你可以通过以下两种方案解决问题:
方案1(推荐,符合依赖倒置设计原则)
调整控制器的构造函数参数类型,直接依赖抽象接口IRepository<SomeReadModel, SomeDto, SomeFilter>,而非具体的SomethingRepository实现类。
修改示例:
// 修改前 public YourController(SomethingRepository repository) // 修改后 public YourController(IRepository<SomeReadModel, SomeDto, SomeFilter> repository)
调整后单元测试无需做类型转换,直接把Mock生成的IRepository实例注入控制器即可,不需要改动仓储层的任何代码,同时也符合面向接口编程的最佳实践。
方案2(适配无法修改控制器定义的场景)
Moq支持Mock带构造参数的具体类,不需要给仓储类额外加无参构造函数,只需要在创建Mock实例时传入构造函数所需的参数即可。
示例代码:
// 假设SomethingRepository的构造函数需要DbContext和其他依赖参数 var mockDb = new Mock<YourDbContext>(); var mockOtherDep = new Mock<IOtherDependency>(); // 构造Mock<SomethingRepository>时按构造参数顺序传入依赖的Mock实例 var mockRepo = new Mock<SomethingRepository>(mockDb.Object, mockOtherDep.Object); // 后续正常Setup方法,注入控制器即可 mockRepo.Setup(r => r.GetListAsync(It.IsAny<SomeFilter>())).ReturnsAsync(yourTestData); var controller = new YourController(mockRepo.Object);
内容的提问来源于stack exchange,提问作者Zenith
相关产品推荐
相关产品推荐

