C#中Mock返回匿名类型的泛型Repository方法遇问题求助
问题分析与解决
你的问题核心是泛型方法的类型参数不匹配:
- 实际调用
Get方法时,传入的是结构为{DateTime TimeStamp, double? Value}的匿名类型作为TResult,此时泛型方法的类型参数是这个专属的匿名类型。 - 但你在Setup里把
TResult硬编码成了object,并用Func<Model, object>匹配参数,Moq无法将实际的Func<Model, 匿名类型>与该Setup匹配,加上开启了MockBehavior.Strict,因此抛出未匹配到Setup的异常。
正确的Mock写法
需要用泛型Setup匹配任意TResult类型的调用,而非固定为object。修改后的代码如下:
var mock = new Mock<IModel>(MockBehavior.Strict); // 用泛型Setup匹配所有TResult类型的Get方法调用 mock.Setup<TResult>(repo => repo.Get( It.IsAny<IEnumerable<int>>(), It.IsAny<Func<Model, TResult>>())) .Returns((IEnumerable<int> ids, Func<Model, TResult> getValues) => { // 构造模拟的Model实例 var mockModel = new Model { TimeStamp = DateTime.Parse("2022-12-12T16:00:00"), Value = 3_000_000 }; // 用传入的委托将Model转换为调用方需要的TResult类型(含匿名类型) return new[] { getValues(mockModel) } as IReadOnlyCollection<TResult>; });
关键说明
- 用
Setup<TResult>显式声明泛型Setup,让Moq兼容所有TResult类型的Get方法调用。 - 在Returns逻辑中直接使用传入的
getValues委托,将模拟的Model实例转换为调用方预期的TResult类型,确保返回类型完全匹配,避免类型转换问题。 - 无需提前定义
_mockValue,通过构造真实Model实例再转换的方式,更贴合原方法的业务逻辑。
内容的提问来源于stack exchange,提问作者Wojciech Szabowicz
相关产品推荐
相关产品推荐

