测试Repo类时,如何正确Stub repoClient嵌套属性的all方法?
this.api.Pipelines.all 问题背景
我想要测试Repo类的getLatestProjectPipeline方法,该方法最终会调用依赖的repoClient实例的嵌套属性方法this.api.Pipelines.all。需注意,repoClient仅包含属性,无直接方法(比如this.api.Pipelines是属性,需调用其下的方法)。当前用sinon.createStubInstance(repoClient)会报错:Error: Found no methods on object to which we could apply mutations;但不使用该方法则会实际调用repoClient构造函数,这是我不希望的,请问如何正确Stubthis.api.Pipelines.all方法?
解决方案
别用sinon.createStubInstance了,手动构建带嵌套属性的模拟对象,单独Stub目标方法就行,步骤如下:
手动构建模拟的repoClient实例
逐层搭建嵌套的属性结构,最后用sinon.stub()替换all方法:// 先Stub最底层的all方法,传入测试需要的模拟返回值 const mockPipelines = { all: sinon.stub().resolves({ id: 123, name: "测试管道" }) }; // 构建api属性,包含Pipelines const mockApi = { Pipelines: mockPipelines }; // 最终的模拟repoClient实例 const mockRepoClient = { api: mockApi };把模拟实例注入Repo类
确保你的Repo类是通过构造函数或者 setter 接收repoClient的,测试时直接传上面的mockRepoClient,完全不会触发真实的repoClient构造函数:// 假设Repo的构造函数接收repoClient参数 const repo = new Repo(mockRepoClient);验证Stub的调用(可选)
测试执行完后,可以检查all方法的调用情况:// 验证方法被调用过一次 sinon.assert.calledOnce(mockPipelines.all); // 或者验证调用时传的参数是否符合预期 sinon.assert.calledWith(mockPipelines.all, "预期参数");
原因说明
sinon.createStubInstance是用来自动Stub对象原型上的方法的,但你的repoClient只有属性,没有定义在原型上的方法,所以它找不到可修改的方法才会报错。手动构建嵌套结构+单独Stub目标方法,更适配这种纯属性嵌套的场景。
内容的提问来源于stack exchange,提问作者JC1

