Sinon Stub 每次返回不同的值

Sinon Stub Different Value returned each time

我是 TypeScript/JavaScript 的新手,但我有一个可用的 VScode 扩展,我对此非常满意。我的问题是我的摩卡测试。我有以下功能

export async function getPackInfo (): Promise<IPackInfo> {
  let validChars = '^[0-9a-zA-Z-]+$'
  let ref
  ref = await getInput('Pack Reference (lowercase and (-) only)', 'pack-reference', 'my-first-pack')
  if (!ref.match(validChars)) {
    vscode.window.showErrorMessage('Pack name can only contain letters, numbers and dashes', 'Got it')
    return Promise.reject(new Error('Pack name can only contain letters, numbers and dashes. Pack will not be created correctly.'))
  }
  console.log(ref)
  let packname = ref.replace(/-/g, ' ').toLowerCase()
  .split(' ')
  .map((s) => s.charAt(0).toUpperCase() + s.substring(1))
  .join(' ')
  console.log(packname)
  let author
  if (getSetting('defaultAuthor')) {
    console.log('Got setting')
    author = getSetting('defaultAuthor')
  } else {
    console.log('Need input')
    author = await getInput('Pack Author', 'Pack Author', 'John Doe')
  }
  console.log(author)

  let email
  if (getSetting('defaultEmail')) {
    email = getSetting('defaultEmail')
  } else {
    email = await getInput('Author Email', 'Author Email', 'john@example.com')
  }
  console.log(email)
  if (!author || !email) {
    throw new Error('Pack author or email not defined')
  }
  // Write Pack Config File
  let data: IPackInfo = {
    'ref': ref,
    'packname': packname,
    'author': author,
    'email': email
  }
  return data
}

此函数调用另一个名为 getInput 的函数,后者调用 vscode.window.showInputBox:

export async function getInput (prompt: string, placeholder: string, defaultValue: string): Promise<string> {
  let value = await vscode.window.showInputBox({ prompt: prompt, placeHolder: placeholder, value: defaultValue }).then(function(value) {
    if (value) {
      resolve(value)
    }
    throw new Error('No value for prompt')
  })

我正在尝试测试 return 函数中的数据是否正确。我的测试目前看起来像这样:

    it('Check that packname is converted correctly', function (done) {
      let mockGetInput
      mockGetInput = sinon.stub(vscode.window, 'showInputBox')
      mockGetInput.onFirstCall().resolves('ref-pack-here')
      mockGetInput.onSecondCall().resolves('Test Author')
      mockGetInput.onThirdCall().resolves('example@example.com')
      getPackInfo().then((res) => {
        let output = res['ref']
        console.log(`Output: ${res['packname']}`)
        console.log(`Output: ${res['author']}`)
        console.log(`Output: ${res['email']}`)
        console.log(`Output: ${res['ref']}`)
      }).catch(error => {
        console.log(error)
      })
      done()
      mockGetInput.restore()
    })

我已经这样做好几天了,但我无法让每次调用都具有不同的值!

第一次调用 return 正确,但所有后续调用都没有 return 任何东西。

如果有更好的方法,我很乐意尝试!

看来您需要对 async 代码进行一些修复。


现在 getInput 总是 解析为 undefinedresolvethen 子句中未定义,因此 Promise 总是以错误拒绝,但即使该问题不存在 value 也会 否则从 vscode.window.showInputBox 返回。

您可以通过将其更改为以下内容来解决这些问题:

export async function getInput (prompt: string, placeholder: string, defaultValue: string): Promise<string> {
  const value = await vscode.window.showInputBox({ prompt: prompt, placeHolder: placeholder, value: defaultValue });
  if (value) {
    return value;
  }
  throw new Error('No value for prompt')
}

您正在正确创建模拟,您只需要等待 getPackInfo 返回的 Promise 解决,然后再恢复模拟并结束测试。

现在它正在调用 getPackInfo,然后立即调用 done,恢复模拟,并在 getPackInfo 中的任何 async 代码之前结束测试甚至有机会 运行.

解决这个问题的最简单方法是使用 async 测试函数并在 Promise:

上调用 await
it('Check that packname is converted correctly', async () => {  // async test function
  let mockGetInput;
  mockGetInput = sinon.stub(vscode.window, 'showInputBox');
  mockGetInput.onFirstCall().resolves('ref-pack-here');
  mockGetInput.onSecondCall().resolves('Test Author');
  mockGetInput.onThirdCall().resolves('example@example.com');
  const res = await getPackInfo();  // await the Promise
  console.log(`Output: ${res['packname']}`);
  console.log(`Output: ${res['author']}`);
  console.log(`Output: ${res['email']}`);
  console.log(`Output: ${res['ref']}`);
  mockGetInput.restore();
});