sinon:如何模拟从另一个函数返回的函数

时间:2017-11-03 14:36:36

标签: javascript node.js git unit-testing sinon

我试图与simple-git合作。我需要编写一些单元测试,为此我需要使用sinon模拟一些函数。我遇到的问题是我的嘲笑不会传播到我的测试文件中。

例如,在测试文件中,我有:

const git = require('simple-git/promise')
function func () {
    var promise
    if (repo_exists()) {
        promise = git().silent(true).clone('http://github.com/me/my-repo.git')
    } else {
        promise = git('my-repo').silent(true).pull('origin','master')
    }

    promise.then(() => {
        // do more stuff
    })
}

在我的测试文件中,我试过这个:

const git = require('simple-git/promise')()
sinon.stub(git, 'silent').callsFake(() => {
  return {
    clone: () => {
      console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~')
      console.log('calling clone')
      console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~')
      return new Promise((resolve, reject) => {
        console.log('clone')
        resolve()
      })
    },
    pull: () => {
      console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~')
      console.log('calling pull')
      console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~')
      return new Promise((resolve, reject) => {
        console.log('pull')
        resolve()
      })
    }
  }
})

但是被嘲笑的函数不会被调用。我假设原因是require('simple-git/promise')返回一个函数,它本身返回包含我想要模拟的函数的对象,但我不知道如何处理它。

1 个答案:

答案 0 :(得分:1)

你没错,当调用git()时,它每次都会返回一个新对象。此对象的方法最终代理到Githttps://github.com/steveukx/git-js/blob/master/src/git.js

的实例

作为一个选项,您可以存储_run的内部Git.prototype方法(负责安排执行命令的方法):

const Git = require('simple-git/src/git');

sinon.stub(Git.prototype, '_run').callsFake(function (command, cb) {
  console.log('called command', command)

  // to indicate success (will resolve eventual promise)
  cb.call(this, null, 'any message');

  // OR to indicate failure (will reject eventual promise)
  Git.fail(this, 'error message', cb);

  return this;
});

注意,callsFake下的非箭头功能对于保留this至关重要,需要return this才能符合原始行为(https://github.com/steveukx/git-js/blob/master/src/git.js#L1271)。