FakeItEasy中MustHaveHappened断言报错:伪造的GetResult方法未被调用
解决FakeItEasy断言失败:伪造的ILister未被调用的问题
你已经精准定位了问题核心——GetByList的构造函数内部直接实例化了真实的SecurityProjectLister,完全没用到测试里创建的伪造ILister实例,导致Fake的方法配置和后续断言都无法命中真实调用逻辑。下面是具体的修复方案:
1. 重构GetByList,通过依赖注入接收ILister
修改端点的构造函数,不再自行创建SecurityProjectLister,而是让外部注入ILister实例,同时修正代码里的笔误:
private readonly ILister _lister; // 构造函数注入ILister,让外部控制实例来源 public GetByList(ILister lister) { _lister = lister; } // 如果你业务上必须保留IDbConnectionFactory依赖,可调整为: // public GetByList(IDbConnectionFactory dbConnectionFactory) // { // var dataService = new DataService(dbConnectionFactory); // _lister = new SecurityProjectLister(dataService); // 修正原代码中变量名错误 // } // 但这种方式仍无法在测试中替换Lister,更推荐直接注入ILister [HttpGet] public IActionResult GetFieldsByRange([FromQuery][Range(0, int.MaxValue)] int skip = 0, [FromQuery][Range(0, 1000)] int top = 1000) { // 修正字段名,与类内私有字段保持一致 ResponseList response = _lister.GetResult(skip, top); return Ok(response); }
2. 调整测试代码,将伪造的ILister注入GetByList
现在测试可以把Fake的ILister传给GetByList的构造函数,确保端点使用的是伪造实例:
public class GetByListTests { [Fact] public void GetByList_GetFieldsByRange_Test() { // 创建Fake的ILister实例 ILister fakeLister = A.Fake<ILister>(); // 配置Fake方法的返回结果 A.CallTo(() => fakeLister.GetResult(A<int>._, A<int>._)) .Returns(new ResponseList(1, new List<RecordsValues>())); // 将Fake实例注入到GetByList中 GetByList getByList = new GetByList(fakeLister); // 执行测试方法 var result = (OkObjectResult)getByList.GetFieldsByRange(); // 断言Fake方法被调用 A.CallTo(() => fakeLister.GetResult(A<int>._, A<int>._)).MustHaveHappened(); Assert.NotNull(result); Assert.Equal(200, result.StatusCode); } }
额外说明
如果业务上GetByList必须依赖IDbConnectionFactory来创建底层服务,可考虑用工厂模式抽象SecurityProjectLister的创建逻辑,但最直接的测试友好方案还是直接注入ILister——这样测试时无需关心Lister的内部依赖,只需验证交互和返回值即可。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

