使用Sinon Stub simple-git方法失败,改用proxyquire仍无效
问题:Sinon Stub simple-git 无效,改用proxyquire仍失败
我尝试用Sinon对simple-git库的方法做Stub来测试代码,但Stub完全被忽略。后来发现是因为测试方法里创建了新的simple-git实例,于是改用proxyquire,可问题还是没解决,哪里操作错了?
待测试代码
const git = require('simple-git'); module.exports.getGitPushCommandChildProcess = async (centralisedRepoFolderPath, branchName) => { logger.debug('#### executing getGitPushCommandChildProcess()'); logger.debug(` [arg1] - centralisedRepoFolderPath: ${centralisedRepoFolderPath}`); logger.debug(` [arg2] - branchName: ${branchName}`); await git(centralisedRepoFolderPath) .push('origin', branchName); };
原测试代码
it('merge request creation should succeed when running locally', async () => { // this will not get set when run locally process.env.PRIMARY_MR_ORIGINATOR_USERNAME = ''; mockfs({ 'exchange-config': mockfs.load('test/unit/input-files/auto-merge-request/exchange-config') }); sandbox.stub(git(), 'push').callsFake(() => Promise.resolve('pushed was called')); const { mrOpened, executionErrors } = await autoMergeRequestModule.openNewMergeRequest( apiObject, mockConfig, false ); assert.strictEqual(executionErrors.toString(), ''); assert.strictEqual(mrOpened, true); });
更新后的proxyquire尝试
const gitStub = sinon.stub().callsFake(() => Promise.resolve()); proxyquire('../../../../src/publishing/auto-merge-request/lib/auto-merge-request-lib', { 'simple-git': gitStub });
问题分析与解决方案
原测试的核心问题
sandbox.stub(git(), 'push') 的问题在于:每次调用git()都会生成全新的simple-git实例,你Stub的只是这个临时实例的push方法,但业务代码会重新调用git(centralisedRepoFolderPath)生成另一个独立实例,Stub自然不会生效。
proxyquire尝试的错误
你的gitStub只模拟了simple-git函数本身,但simple-git的调用逻辑是先调用函数传入路径,返回实例对象,再调用该对象的push方法。现在的Stub只返回Promise,没有提供带push方法的实例对象,无法Stub到目标调用。
正确的proxyquire用法
需要让simple-git的Stub返回带有Stubbed push方法的对象,具体写法如下:
it('merge request creation should succeed when running locally', async () => { process.env.PRIMARY_MR_ORIGINATOR_USERNAME = ''; mockfs({ 'exchange-config': mockfs.load('test/unit/input-files/auto-merge-request/exchange-config') }); // 1. 创建实例Stub,包含push方法的Stub const gitInstanceStub = { push: sinon.stub().resolves() // 模拟push方法返回成功Promise }; // 2. 让simple-git的Stub每次调用都返回这个实例Stub const gitStub = sinon.stub().returns(gitInstanceStub); // 3. 用proxyquire加载目标模块,替换simple-git为我们的Stub const autoMergeRequestModule = proxyquire('../../../../src/publishing/auto-merge-request/lib/auto-merge-request-lib', { 'simple-git': gitStub }); // 4. 执行测试逻辑 const { mrOpened, executionErrors } = await autoMergeRequestModule.openNewMergeRequest( apiObject, mockConfig, false ); // 5. 可选:验证push方法是否被正确调用 sinon.assert.calledWith(gitInstanceStub.push, 'origin', /* 预期的分支名 */); assert.strictEqual(executionErrors.toString(), ''); assert.strictEqual(mrOpened, true); });
关键注意点
- 必须使用proxyquire返回的模块对象(
autoMergeRequestModule)执行测试,不能提前加载模块再替换,否则模块会使用原始的simple-git依赖。 - 若需要模拟simple-git的链式调用(比如
git().add().commit().push()),需要让实例Stub的每个方法都返回自身:const gitInstanceStub = { push: sinon.stub().resolves(), add: sinon.stub().returnsThis(), commit: sinon.stub().returnsThis() };
内容的提问来源于stack exchange,提问作者sdicola
相关产品推荐
相关产品推荐

