NUnit问题:使用实际参数配置Mock方法时失效
问题描述
原本使用Moq配置的Mock能正常工作:
Mock<IDeclarationQuery> _declarationQueryMock = new Mock<IDeclarationQuery>(); _declarationQueryMock.Setup(x => x.FindDeclarationDetailAsync(It.IsAny<FindDeclarationModel>(), cancellationToken)) .ReturnsAsync(declarationDetailResponse);
测试时调用FindDeclarationDetailAsync可正常获取declarationDetailResponse。
但改为使用真实参数精准匹配后,Mock配置失效,方法返回null:
FindDeclarationModel findDeclarationModel = new FindDeclarationModel() { CountryCode = "AFG", DeclarationTypeId = DeclarationTypes.ADPA, Year = 2022 }; _declarationQueryMock.Setup(x => x.FindDeclarationDetailAsync(findDeclarationModel, cancellationToken)) .ReturnsAsync(declarationDetailResponse);
已确认调试时传入的FindDeclarationModel对象结构和值完全一致,但问题依旧。
问题原因与解决方案
原因
你猜的没错,Moq默认对引用类型是按引用地址匹配的,即使两个对象的属性值完全相同,只要不是同一个实例,Moq就会认为参数不匹配,导致Setup的逻辑不生效,返回默认值(null)。
解决方案
有三种常用的解决方式:
1. 重写FindDeclarationModel的Equals和GetHashCode方法
让类型支持值相等比较,这样Moq就能通过属性值判断两个对象是否匹配:
public class FindDeclarationModel { public string CountryCode { get; set; } public DeclarationTypes DeclarationTypeId { get; set; } public int Year { get; set; } public override bool Equals(object obj) { if (obj is not FindDeclarationModel other) return false; return CountryCode == other.CountryCode && DeclarationTypeId == other.DeclarationTypeId && Year == other.Year; } public override int GetHashCode() { return HashCode.Combine(CountryCode, DeclarationTypeId, Year); } }
修改后,原有的Setup代码就能正常按值匹配。
2. 使用It.Is<T>自定义匹配逻辑
不需要修改实体类,直接在Setup时指定属性匹配规则:
_declarationQueryMock.Setup(x => x.FindDeclarationDetailAsync( It.Is<FindDeclarationModel>(model => model.CountryCode == "AFG" && model.DeclarationTypeId == DeclarationTypes.ADPA && model.Year == 2022), cancellationToken)) .ReturnsAsync(declarationDetailResponse);
这种方式灵活,适合临时的匹配需求。
3. 使用It.IsEquivalentTo<T>(Moq 4.13+版本支持)
Moq 4.13及以上提供了It.IsEquivalentTo<T>方法,会自动比较对象的所有公共属性值是否相等,无需重写Equals:
using Moq; _declarationQueryMock.Setup(x => x.FindDeclarationDetailAsync( It.IsEquivalentTo(findDeclarationModel), cancellationToken)) .ReturnsAsync(declarationDetailResponse);
这种方式简洁,适合快速实现值匹配。
内容的提问来源于stack exchange,提问作者Pawan Nogariya
相关产品推荐
相关产品推荐

