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

使用FakeItEasy伪造LINQ查询转字典时遇‘非伪造对象’错误

问题:FakeItEasy配置LINQ链式调用时抛出“未识别为假对象”错误

要测试的生产代码逻辑:从数据库查询指定物种的动物,按Code去重后生成字典

var animals = _dataService.Query<Animal>()
    .Where(x => x.Species == 2)
    .GroupBy(i => i.Code)
    .Select(i => i.FirstOrDefault())
    .ToDictionary(i => i.Code, i => i);

原测试代码配置:

// Arrange
var fakeIDataService = A.Fake<IDataService>();
var fakeMapper = A.Fake<IMapper>();

var monkey = new Animal
{
    Id = 1,
    Description = "Monkey",
    Code = "MKY",
    Species = 2
};

var animals = new Dictionary<string, Animal>() 
{ 
    { monkey.Code, monkey} 
};

A.CallTo(() => fakeIDataService.Query<Animal>()
    .Where(x => x.Species == 2)
    .GroupBy(i => i.Code)
    .Select(i => i.FirstOrDefault())
    .ToDictionary(i => i.Code, i => i)
).Returns(animals);

// Act
var service = new ProcessAnimalLines(fakeIDataService, fakeMapper);

// Assert
A.CallTo(() => fakeIDataService.SaveChangesAsync()).MustHaveHappened(Repeated.Exactly.Once);

运行测试时抛出错误:

System.ArgumentException : The specified object is not recognized as a fake object.

错误原因

FakeItEasy只能拦截**假对象(Fake)**上的方法调用,而Query<Animal>()返回的IQueryable<Animal>/IEnumerable<Animal>是真实的集合类型(不是Fake对象),无法被FakeItEasy捕获后续的LINQ链式调用(Where/GroupBy等),因此配置整个LINQ链的返回会触发报错。

正确测试写法

应该只FakeQuery<Animal>()方法,让它返回预先构造好的测试数据集合,然后让真实的LINQ逻辑执行去重生成字典,这样既符合生产代码逻辑,又能正确完成测试:

// Arrange
var fakeIDataService = A.Fake<IDataService>();
var fakeMapper = A.Fake<IMapper>();

// 构造测试数据,包含重复Code的动物,模拟去重场景
var testAnimals = new List<Animal>
{
    new Animal { Id = 1, Description = "Monkey", Code = "MKY", Species = 2 },
    new Animal { Id = 2, Description = "Duplicate Monkey", Code = "MKY", Species = 2 },
    new Animal { Id = 3, Description = "Tiger", Code = "TGR", Species = 2 }
};

// 仅Fake Query方法,返回测试集合(如果返回IQueryable则用AsQueryable转换)
A.CallTo(() => fakeIDataService.Query<Animal>()).Returns(testAnimals.AsQueryable());

// Act
var service = new ProcessAnimalLines(fakeIDataService, fakeMapper);
service.Process(); // 调用服务中执行目标逻辑的方法

// Assert
A.CallTo(() => fakeIDataService.SaveChangesAsync()).MustHaveHappened(Repeated.Exactly.Once);

说明

  • 这种方式测试的是真实的业务逻辑(去重生成字典),而不是跳过LINQ逻辑直接返回结果,测试更准确。
  • 如果生产代码中Query<Animal>()返回的是IEnumerable<Animal>,直接返回testAnimals即可,无需AsQueryable()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:32:14