如何用Sinon多次包装方法并按参数返回不同对象?解决重复包装报错
解决Sinon中多次包装同一方法(getRepository)的问题
这个问题我之前也碰到过,核心原因是你连续两次调用sandbox.mock(Salesforce).expects('getRepository'),Sinon的mock机制会直接替换目标方法,第二次尝试包装同一个方法时就会触发TypeError: Attempted to wrap getRepository which is already wrapped错误。
下面给你两种可行的解决思路,都能实现让getRepository根据传入的不同参数返回不同仓库实例的需求:
方法一:使用Stub替代Mock(推荐)
Stub比Mock更适合这种“根据参数返回不同结果”的场景,它支持链式设置不同参数对应的返回值,不会出现重复包装的问题:
// 先创建两个仓库实例,并分别mock它们的方法 const servicePackagesOfferingRepository = new Repository(ServicePackageOffering); sandbox.mock(servicePackagesOfferingRepository) .expects('findOneById') .withArgs(inputModel.servicePackageOfferingId) .resolves({}); const serviceCallRepository = new Repository(ServiceCall); sandbox.mock(serviceCallRepository) .expects('save') .once(); // 用Stub包装getRepository,根据传入的参数返回对应的仓库实例 sandbox.stub(Salesforce, 'getRepository') .withArgs(ServicePackageOffering).returns(servicePackagesOfferingRepository) .withArgs(ServiceCall).returns(serviceCallRepository);
这样设置后,当代码第一次调用Salesforce.getRepository(ServicePackageOffering)时会返回你创建的第一个仓库实例,第二次调用Salesforce.getRepository(ServiceCall)时返回第二个实例,完美匹配你的业务逻辑。
方法二:在同一个Mock中设置多调用行为
如果你更倾向于用Mock来严格验证调用次数和顺序,可以在同一个Mock对象上通过onCall()方法指定每次调用的行为:
// 先创建两个仓库实例 const servicePackagesOfferingRepository = new Repository(ServicePackageOffering); const serviceCallRepository = new Repository(ServiceCall); // 创建一个针对getRepository的Mock,明确预期会被调用两次 const getRepoMock = sandbox.mock(Salesforce) .expects('getRepository') .twice(); // 设置第一次调用的行为:传入ServicePackageOffering时返回对应仓库 getRepoMock.onCall(0) .withArgs(ServicePackageOffering) .returns(servicePackagesOfferingRepository); // 设置第二次调用的行为:传入ServiceCall时返回对应仓库 getRepoMock.onCall(1) .withArgs(ServiceCall) .returns(serviceCallRepository); // 最后mock两个仓库的具体方法 sandbox.mock(servicePackagesOfferingRepository) .expects('findOneById') .withArgs(inputModel.servicePackageOfferingId) .resolves({}); sandbox.mock(serviceCallRepository) .expects('save') .once();
这种方式通过onCall(index)指定第N次调用的参数和返回值,既避免了重复包装的问题,也能严格验证getRepository的调用次数和顺序。
内容的提问来源于stack exchange,提问作者Philipp Spinnler
相关产品推荐
相关产品推荐

