如何配置Mock使AddString仅返回一次true以终止while循环?
解决Moq中AddString方法仅返回一次true的问题
你遇到的问题是因为当前的Moq Setup让AddString每次调用都返回true,导致while循环无限执行。要实现第一次调用返回true,后续所有调用返回false,可以通过Moq的闭包变量或者序列返回的方式来实现,下面给你两种实用的代码方案:
方案一:使用计数器变量(通用无依赖)
这种方法不需要额外扩展,利用闭包变量记录调用次数,精准控制返回值:
var loginName = "12345"; // 初始化调用计数器 int callCount = 0; cacheRepository.Setup(m => m.AddString( // 匹配任意由ResetCodeCacheKey和随机code生成的key It.Is<string>(key => key.StartsWith($"{Resources.ResetCodeCacheKey}_")), loginName )) .Returns(() => { // 每次调用计数器自增 callCount++; // 仅第一次调用返回true,后续全部返回false return callCount == 1; });
细节说明:
- 这里用
It.Is<string>(...)来匹配符合格式的key,比硬编码更灵活(因为测试中的code是随机生成的); - 闭包里的
callCount会在每次调用AddString时递增,确保只有第一次返回true,完美终止while循环。
如果测试中code是固定值,需要严格匹配特定key,可以把匹配条件换成你原来的写法:
var targetCode = "testCode123"; // 测试用的固定code cacheRepository.Setup(m => m.AddString( string.Format("{0}_{1}", Resources.ResetCodeCacheKey, targetCode), loginName )) .Returns(() => { callCount++; return callCount == 1; });
方案二:使用Moq的序列返回(需Moq 4.16+)
如果你使用的是较新版本的Moq(4.16及以上),可以直接用Returns的序列重载,写法更简洁直观:
var loginName = "12345"; cacheRepository.Setup(m => m.AddString( It.Is<string>(key => key.StartsWith($"{Resources.ResetCodeCacheKey}_")), loginName )) // 第一个调用返回true,之后所有调用都返回false .Returns(true, false);
这种写法直接指定返回值的顺序:第一次调用返回true进入循环体,第二次调用返回false触发循环终止,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Gautam
相关产品推荐
相关产品推荐

