使用Moq模拟IMemoryCache时无法获取键对应值的问题
问题分析与解决方案
你的测试失败核心源于几个关键错误,以下是具体问题和修正方案:
1. Mock的TryGetValue与存入值完全无关
你在GetMemoryCache方法中给TryGetValue设置的输出参数是初始为null的expectedModel,这个变量和你调用memoryCache.Set存入的expectedValue没有任何关联,导致GetTaskModel调用TryGetValue时始终返回null。
2. 泛型参数类型不匹配
你调用GetTaskModel<Task<It.IsAnyType>>(expectedKey),但实际存入缓存的是string类型的"expectedValue",model as T会因类型不匹配返回null。
3. Mock缓存操作未正确联动
你手动调用memoryCache.Set(expectedKey, expectedValue),但mock的Set方法未被配置为更新TryGetValue的返回值;同时服务实例使用的缓存应与操作的mock实例保持一致,无需额外创建。
修正后的测试代码
[Fact] public async Task GetTaskModel_GivenTask_ReturnsTask() { // Arrange var expectedKey = "expectedKey"; string expectedValue = "expectedValue"; // 配置TryGetValue:传入指定key时返回对应值 _memoryCacheMock .Setup(x => x.TryGetValue(expectedKey, out It.Ref<object>.IsAny)) .Callback((object key, out object value) => value = expectedValue) .Returns(true); // 可选:验证Set方法是否按预期调用 _memoryCacheMock .Setup(x => x.Set(expectedKey, expectedValue, TimeSpan.FromMinutes(10))) .Verifiable(); var service = new BackgroundTaskTrackerService(_memoryCacheMock.Object); service.SetTaskModel(expectedKey, expectedValue); // Act var result = await service.GetTaskModel<string>(expectedKey); // Assert Assert.NotNull(result); Assert.Equal(expectedValue, result); _memoryCacheMock.Verify(); }
关键修正说明
- 用
It.Ref<object>.IsAny配合Callback动态绑定TryGetValue的输出值,确保与存入数据一致。 - 明确泛型参数为
string,与存入类型匹配,避免类型转换失败。 - 使用服务自身的
SetTaskModel方法存入数据,贴合真实业务流程。 - 将测试改为
async Task,直接await异步方法,避免Result可能引发的异步问题。 - 可选添加验证逻辑,确保
Set方法按预期被调用。
内容的提问来源于stack exchange,提问作者HappyQuest
相关产品推荐
相关产品推荐

