xUnit注入ServiceProvider实现缓存依赖注入时遇错误求助
在xUnit中注入ServiceProvider实现缓存依赖注入及错误解决
错误原因
你遇到的ServiceProviderServiceExtensions.GetRequiredService may not be used in setup / verification expressions错误,本质是Moq不允许在Setup或Verify的表达式逻辑里执行实际的服务解析操作。Setup/Verify是用来定义模拟行为、验证调用匹配规则的,不是执行真实服务获取的地方。
正确实现步骤
1. 搭建测试用的依赖注入容器
先通过ServiceCollection注册缓存服务(比如IMemoryCache)和其他业务依赖,再构建ServiceProvider。
2. 提前解析所需服务,避免在Moq表达式中调用GetRequiredService
在测试类构造函数或测试方法开头,先从容器中取出缓存实例或其他服务,再用于测试逻辑或Moq配置。
代码示例
基础缓存测试示例
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Caching.Memory; using Xunit; public class CacheDependencyTests { private readonly IMemoryCache _cache; private readonly IServiceProvider _serviceProvider; public CacheDependencyTests() { // 构建服务容器 var services = new ServiceCollection(); // 注册内存缓存 services.AddMemoryCache(); // 注册你的业务服务(如果需要) services.AddScoped<IMyCachedService, MyCachedService>(); _serviceProvider = services.BuildServiceProvider(); // 提前解析缓存实例,供测试使用 _cache = _serviceProvider.GetRequiredService<IMemoryCache>(); } [Fact] public void Cache_SetAndGet_ReturnsCorrectValue() { // 直接使用已解析的缓存实例 _cache.Set("test_key", "test_value"); var retrievedValue = _cache.Get<string>("test_key"); Assert.Equal("test_value", retrievedValue); } [Fact] public void BusinessService_UsesCache_Correctly() { // 解析依赖缓存的业务服务 var cachedService = _serviceProvider.GetRequiredService<IMyCachedService>(); var result = cachedService.GetCachedData(); Assert.NotNull(result); } } // 示例业务服务 public interface IMyCachedService { string GetCachedData(); } public class MyCachedService : IMyCachedService { private readonly IMemoryCache _cache; public MyCachedService(IMemoryCache cache) { _cache = cache; } public string GetCachedData() { return _cache.GetOrCreate("data_key", entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5); return "cached_data"; }); } }
修复Moq相关错误的示例
错误写法(触发报错)
// 错误:在Setup表达式中调用GetRequiredService mockService.Setup(s => s.DoSomething(_serviceProvider.GetRequiredService<IMemoryCache>())) .Returns(true);
正确写法
// 先解析缓存实例,再传入Setup表达式 var cache = _serviceProvider.GetRequiredService<IMemoryCache>(); mockService.Setup(s => s.DoSomething(cache)) .Returns(true);
关键注意点
- 永远不要在Moq的Setup/Verify表达式中执行
GetRequiredService这类实际方法调用,这些表达式只能包含成员调用、参数匹配逻辑。 - 测试类的依赖解析尽量放在构造函数中,确保每个测试方法都能拿到干净的服务实例(如果需要隔离,也可以在每个测试方法中重新构建容器)。
内容的提问来源于stack exchange,提问作者Dev-lop-er
相关产品推荐
相关产品推荐

