使用AutoFake存根SUT自身方法时提示“未识别为假对象”问题求助
解决AutoFake存根SUT自身虚方法的ArgumentException问题
这个问题的核心原因很明确:你通过FakeResolver.Resolve<ProductQueryService>()获取的_sut是真实的类实例,而不是FakeItEasy创建的fake对象——FakeItEasy只能对它自己生成的fake实例进行方法存根,自然会抛出"The specified object is not recognized as a fake object"异常。
下面是两种可行的解决思路:
方法1:让AutoFake生成SUT的Fake实例(推荐)
直接请求AutoFake创建并冻结Fake<ProductQueryService>类型,这样你就能得到一个可被FakeItEasy拦截的fake实例,进而存根它的虚方法:
AutoFake FakeResolver = new AutoFake(); // 生成并冻结ProductQueryService的fake实例 var fakeSutWrapper = FakeResolver.Freeze<Fake<ProductQueryService>>(); // 对fake实例的虚方法进行存根 A.CallTo(() => fakeSutWrapper.Object.GetLookupCache()).Returns(Task.FromResult(fakeData)); // 获取可测试的SUT实例 ProductQueryService _sut = fakeSutWrapper.Object; // 执行测试 List<BrandDto> brands = await _sut.GetBrands();
这种方式的好处是AutoFake依然会自动注入ProductQueryService所需的所有依赖,同时让你能够控制SUT自身的虚方法行为。
方法2:手动创建SUT的派生类(适合需要部分真实逻辑的场景)
如果你需要保留SUT的大部分真实逻辑,只重写特定虚方法,可以手动创建一个测试用的派生类:
// 测试专用的派生类,重写需要存根的方法 public class TestableProductQueryService : ProductQueryService { private readonly Task<YourFakeDataType> _fakeLookupCache; public TestableProductQueryService(/* 注入SUT所需的依赖 */, Task<YourFakeDataType> fakeLookupCache) : base(/* 传递依赖给父类 */) { _fakeLookupCache = fakeLookupCache; } public override Task<YourFakeDataType> GetLookupCache() { return _fakeLookupCache; } }
然后在测试中使用这个派生类:
AutoFake FakeResolver = new AutoFake(); // 注入依赖并创建测试用实例 var _sut = new TestableProductQueryService( FakeResolver.Resolve<IDependency1>(), FakeResolver.Resolve<IDependency2>(), Task.FromResult(fakeData) ); // 执行测试 List<BrandDto> brands = await _sut.GetBrands();
这种方式更灵活,但需要手动处理依赖注入,适合对SUT真实逻辑依赖较强的场景。
补充说明
AutoFake的Resolve<T>方法默认行为是:
- 如果
T是接口或抽象类,会生成对应的fake实例 - 如果
T是具体类,会激活真实的类实例(使用AutoFixture的对象生成逻辑)
所以当你需要存根具体类的虚方法时,必须显式请求Fake<T>类型,而不是直接Resolve<T>。
内容的提问来源于stack exchange,提问作者Caner Patır
相关产品推荐
相关产品推荐

