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

使用Xunit与MOQ:如何Mock返回List的泛型方法

如何Mock泛型仓储的GetItems方法返回指定List?

我正在使用.NET Core 3.1、MOQ与Xunit,采用工作单元(UOW)和仓储模式开发。我的泛型仓储中有如下GetItems方法,请问如何Mock该方法使其返回指定List?

泛型仓储中的GetItems方法

public async Task<List<TType>> GetItems<TType>(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderBy, Expression<Func<T, TType>> select) where TType : class
{
    var Query = await _context.Set<T>().AsNoTracking().Where(predicate).OrderBy(orderBy).Select(select).ToListAsync();
    return Query;
}

我尝试的代码

_artikelAfwijkingen = new List<ArtAfwijking>()
{
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 80, Nr_Filiaal = 0},
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 0, Nr_Filiaal = 0},
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 100, Nr_Filiaal = 0}
};
        
artAfwijkingRepository.CallBase = true;
artAfwijkingRepository.Setup(m => m.GetItems<ArtAfwijking>(It.IsAny<Expression<Func<ArtAfwijking, bool>>>(), It.IsAny<Expression<Func<ArtAfwijking, object>>>(), It.IsAny<Expression<Func<ArtAfwijking, ArtAfwijking>>>()))
                .Returns(Task.FromResult(_artikelAfwijkingen));;

var repository = artAfwijkingRepository.Object;
var artAfwijk = await repository.GetArtAfwijkingAsync("ARTIKEL_X", "ACHM", 80, 0, false);

ArtAfwijkingRepository中的GetArtAfwijkingAsync方法

public async Task<ArtAfwijking> GetArtAfwijkingAsync(string artikelCode, string instantieCode, int licentieNummer, short? filiaalNummer, bool overnemenOmschrijving)
{
    List<ArtAfwijking> artikelAfwijkingen = await GetItems(a => a.Kd_Artikel == artikelCode && a.Kd_Instantie == instantieCode && a.Nr_Filiaal == filiaalNummer, a => a.Kd_Artikel, a => a);
    if (artikelAfwijkingen.Count == 1)
        return (artikelAfwijkingen[0]);
    return null;
}

正确的Mock实现方案

你的代码核心问题在于CallBase = true会触发基类的真实方法调用,绕过Mock逻辑。调整后的代码如下:

_artikelAfwijkingen = new List<ArtAfwijking>()
{
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 80, Nr_Filiaal = 0},
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 0, Nr_Filiaal = 0},
    new ArtAfwijking { Kd_Artikel = "Artikel_1", Kd_Instantie = "ACHM", LicNumber = 100, Nr_Filiaal = 0}
};

// 移除CallBase = true,确保Mock生效
artAfwijkingRepository.Setup(m => m.GetItems<ArtAfwijking>(
    It.IsAny<Expression<Func<ArtAfwijking, bool>>>(),
    It.IsAny<Expression<Func<ArtAfwijking, object>>>(),
    It.IsAny<Expression<Func<ArtAfwijking, ArtAfwijking>>>()))
.ReturnsAsync(_artikelAfwijkingen); // 使用ReturnsAsync简化异步返回值写法

var repository = artAfwijkingRepository.Object;
var artAfwijk = await repository.GetArtAfwijkingAsync("ARTIKEL_X", "ACHM", 80, 0, false);

关键注意事项

  • 移除CallBase = true:该配置会让MOQ在没有匹配的Setup时调用基类真实方法,直接绕过你的Mock逻辑,导致无法返回预设的List。
  • 使用ReturnsAsync:MOQ提供的异步方法返回值快捷写法,比Task.FromResult更简洁直观。
  • 泛型参数匹配:确保Setup中的GetItems<ArtAfwijking>与实际调用的泛型参数一致,否则Mock不会生效。

如果需要验证传入的表达式是否符合预期,可以将It.IsAny<>替换为具体的表达式匹配逻辑,例如:

artAfwijkingRepository.Setup(m => m.GetItems<ArtAfwijking>(
    It.Is<Expression<Func<ArtAfwijking, bool>>>(expr => /* 这里编写表达式验证逻辑 */),
    It.IsAny<Expression<Func<ArtAfwijking, object>>>(),
    It.IsAny<Expression<Func<ArtAfwijking, ArtAfwijking>>>()))
.ReturnsAsync(_artikelAfwijkingen);

但大多数单元测试场景下,使用It.IsAny<>已经足够覆盖需求。


内容的提问来源于stack exchange,提问作者user3552264

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:45:03