You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:16:03