摩卡测试间歇性结果

Mocha test intermittent result

我正在编写一个 mocha 测试来检查函数运行后文件是否存在。我目前得到的结果是断断续续的。它有时会连续几次通过,然后失败。我对 TypeScript 很陌生,所以我不确定发生了什么。

我检查了我的代码并确保我正确地回答了承诺。

这是我要测试的功能:

export async function writePackConfig (templateFile: TemplateFile, destination: string, filename: string) {
  LogToConsole('Writing pack config file')
  const mappings = await getPackInfo()
  let content = generateTemplate(TemplateFile.packFile, mappings)
  // writeFileContent(join(destination, filename), content, filename, false)
  await writeFile(join(destination, filename), content, { encoding: 'utf8', flag: 'wx+' }, (error) => {
    if (error) {
      throw error
    }
    return Promise.resolve()
  })
}

这就是我测试它的方式:

describe('Testing writePackConfig function', function () {
  let testFolder = join(__dirname, 'writePackConfig-test')
  before('Create testing folder', async () => {
    try {
      removeSync(testFolder)
    } catch {
      console.log('Folder does not exist')
    }
    mkdirSync(testFolder)
    return Promise.resolve()
  })
  before('Create pack.yaml file', async () => {
    let mappings = {
      'ref': 'pack-ref',
      'packname': 'Pack Ref',
      'author': 'Test Author',
      'email': 'example@example.com'
    }
    let stubGetPackInfo = sinon.stub(bootstrapfunctions, 'getPackInfo').resolves(mappings)
    await writePackConfig(TemplateFile.packFile, testFolder, 'write-pack-config-pack.yaml').catch(error => {
      console.log(error)
    })
    stubGetPackInfo.restore()
    return Promise.resolve()
  })
  it('Check that file is written when writePackConfig is run', function () {
    let result = existsSync(join(testFolder, 'write-pack-config-pack.yaml'))
    console.log(result)
    assert.strictEqual(result, true)
  })

它应该 return 正确,因为文件确实存在。然而,它并非总是如此。但是,每次运行时都会创建该文件。

writeFile 异步写入文件,然后调用 callback。它没有 return 任何东西。

所以这一行:

await writeFile(...);

...实际上并没有等待文件被写入,因为该行实际上是这样做的:

await undefined;

...这不会导致编译或 运行 时错误,但也不会等待文件被写入。


为确保测试始终如一地通过,您需要确保 writePackConfig return 一个 Promise 在写入文件之前不会解析。

Node 有一个新的 fs Promises API that is currently Experimental but does have a writeFile 函数,return 是一个 Promise

另一种选择是使用 util.promisify 创建 writeFile 版本,return 是 Promise:

import * as fs from 'fs';
import * as util from 'util';

const writeFile = util.promisify(fs.writeFile);  // <= This writeFile will return a Promise

...那么 writePackConfig 的最后一行就是:

await writeFile(join(destination, filename), content, { encoding: 'utf8', flag: 'wx+' });

...您的测试应该始终如一地通过。