如何让fallback服务提供者返回编译时未知类型参数的Moq实例
解决方案
你遇到的问题核心是需要根据运行时拿到的Type类型动态创建对应Mock实例,不能直接使用编译期的泛型语法new Mock<serviceType>(),通过反射构造泛型Mock类型即可实现需求。
完整修改后的MockServiceProvider代码
public class MockServiceProvider : IServiceProvider { private readonly Dictionary<Type, object> _services = new(); public void RegisterServices(params object[] serviceInstances) { _services.Clear(); foreach (var serviceInstance in serviceInstances) { if (serviceInstance is Mock mock) { var serviceType = mock.GetType().GetGenericArguments().First(); _services.TryAdd(serviceType, mock.Object); } else { _services.TryAdd(serviceInstance.GetType(), serviceInstance); } } } public object GetService(Type serviceType) { if (_services.TryGetValue(serviceType, out var service)) { return service; } // 动态构造对应类型的Mock实例 var mockGenericType = typeof(Mock<>).MakeGenericType(serviceType); // 传入MockBehavior.Loose保证未设置的成员不会抛异常,符合测试默认需求 var mockInstance = (Mock)Activator.CreateInstance(mockGenericType, MockBehavior.Loose)!; // 将生成的Mock实例缓存,保证同一服务类型每次请求都返回同一个实例 _services.Add(serviceType, mockInstance.Object); return mockInstance.Object; } }
逻辑说明
- 利用
typeof(Mock<>)拿到Mock的开放泛型类型,再通过MakeGenericType方法结合运行时的serviceType构造出闭合的泛型Mock类型 - 用
Activator.CreateInstance实例化构造好的泛型Mock类型,传入MockBehavior.Loose参数保证默认Mock不会因为调用未设置的成员抛出异常 - 生成的Mock对象会存入缓存字典,后续同一服务类型的请求会返回同一个实例,方便你后续需要的时候验证Mock的调用情况
修改后你不需要为每个组件的所有依赖手动注册Mock,只需要注册你需要自定义返回逻辑、验证调用的Mock即可,其余依赖会自动生成默认Mock实例,不会再抛出缺少服务的错误。
内容的提问来源于stack exchange,提问作者Ben Rubin
相关产品推荐
相关产品推荐

