如何Mock C#中IDistributedCache的GetStringAsync与SetStringAsync扩展方法?
解决IDistributedCache扩展方法无法Mock/验证的问题
你遇到的错误根源很明确:GetStringAsync和SetStringAsync是静态扩展方法,Moq这类Mock框架无法直接对扩展方法做Setup或验证操作。这些扩展方法本质是封装了IDistributedCache接口的原生抽象方法,只需Mock/验证这些底层原生方法即可。
IDistributedCache的原生核心异步方法
扩展方法最终调用的是接口定义的两个抽象方法:
Task<byte[]> GetAsync(string key, CancellationToken token = default)Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default)
修改你的测试代码
1. 修正GetRecords_with_key测试
把原来验证GetStringAsync的逻辑,改成验证GetAsync,同时匹配字符串转字节数组的默认逻辑:
public async Task GetRecords_with_key() { // Arrange var key = "key"; var cache = _builder.DistributedCache; // 若需模拟缓存返回值,可在此Setup GetAsync // cache.Setup(x => x.GetAsync(key, default)) // .ReturnsAsync(Encoding.UTF8.GetBytes("预期返回内容")); var sut = _builder.Build(); // Act await sut.GetRecordAsync<string>(key); // Assert cache.Verify(x => x.GetAsync(key, It.IsAny<CancellationToken>()), Times.Once); }
2. 修正Set_Records_with_key测试
原测试的Act步骤调用的是GetRecordAsync,这不会触发缓存写入操作,需改成调用SetRecordAsync;同时把验证SetStringAsync的逻辑替换为验证SetAsync,匹配字符串转字节数组的参数:
public async Task Set_Records_with_key() { // Arrange var key = "key"; var value = "cdc"; var expectedValueBytes = Encoding.UTF8.GetBytes(value); var cache = _builder.DistributedCache; var sut = _builder.Build(); // Act await sut.SetRecordAsync(key, value); // Assert cache.Verify(x => x.SetAsync( key, expectedValueBytes, It.IsAny<DistributedCacheEntryOptions>(), It.IsAny<CancellationToken>()), Times.Once); }
额外提示
- 若要模拟缓存未命中的场景,只需在Setup
GetAsync时返回null即可。 - 扩展方法默认使用UTF-8编码转换字符串与字节数组,测试时保持编码一致就能匹配参数。
内容的提问来源于stack exchange,提问作者Noob
相关产品推荐
相关产品推荐

