如何构建等待进程先完成的 mocha 测试?

How do I build a mocha test that waits for a process to finish first?

我正在尝试为我的 Yeoman 生成器编写一个测试,该生成器调用一个命令行实用程序在我搭建的文件夹中生成一些文件。我已经看到了如何设置超时以等待函数完成的各种示例,但我正在努力让它在本地工作。

这是我的测试:

 describe('Should properly scaffold with config for Spring and wsdl2rest', function () {

    before(function () {
      basicProps.name = 'MyAppMock';
      basicProps.package = 'com.generator.mock';
      basicProps.camelVersion = '2.18.2';
      basicProps.camelDSL = 'spring';
      var wsdlPath = path.join(__dirname, '../test/address.wsdl');
      basicProps.wsdl = wsdlPath;
      basicProps.outdirectory = 'src/main/java';

      return helpers.run(path.join(__dirname, '../app'))
        .inTmpDir(function (dir) {
          var done = this.async(); // `this` is the RunContext object.
          fs.copy(path.join(__dirname, '../templates'), dir, done);
          basicProps.outdirectory = path.join(dir, 'src/main/java');
        })
        .withOptions({ wsdl2rest: true })
        .withPrompts({ name: basicProps.name })
        .withPrompts({ camelVersion: basicProps.camelVersion })
        .withPrompts({ camelDSL: basicProps.camelDSL })
        .withPrompts({ package: basicProps.package })
        .withPrompts({ wsdl: basicProps.wsdl })
        .withPrompts({ outdirectory: basicProps.outdirectory })
        .toPromise();
    });

    it('Should create the basic structure two ways', function () {
      assert.file('pom.xml');
      assert.file('README.md');
      assert.file('src/main/resources/META-INF/spring/camel-context.xml');
      assert.file('src/main/resources/META-INF/spring/camel-context-rest.xml')
    });
  });

问题是命令行可执行文件正在完成测试以查看它生成的文件是否存在,所以我得到:

Creating wsdl2rest java output directory
calling: java -jar C:\Users\brianf\Documents\GitHub\generator-camel-project-fork\app\wsdl2rest\target\wsdl2rest-impl-fatjar-0.1.3-SNAPSHOT.jar --wsdl file:///C:/Users/brianf/Documents/GitHub/generator-camel-project-fork/test/address.wsdl --out C:\Users\brianf\AppData\Local\Tempd84f15024327cbe792407e1294ab46a5b4a1080\src\main\java --camel-context C:\Users\brianf\AppData\Local\Tempd84f15024327cbe792407e1294ab46a5b4a1080\src\main\resources\META-INF\spring\camel-context-rest.xml
      1) Should create the basic structure two ways


  11 passing (411ms)
  1 failing

  1) generator-camel:wsdl2rest
       Should properly scaffold with config for Spring and wsdl2rest
         Should create the basic structure two ways:

      AssertionError [ERR_ASSERTION]: src/main/resources/META-INF/spring/camel-context-rest.xml, no such file or directory
      + expected - actual

      -false
      +true

      at convertArgs.forEach.file (node_modules\yeoman-assert\index.js:56:12)
      at Array.forEach (<anonymous>)
      at Function.assert.file (node_modules\yeoman-assert\index.js:54:26)
      at Context.<anonymous> (test\app.js:206:14)



stdout: Retrieving document at 'file:/C:/Users/brianf/Documents/GitHub/generator-camel-project-fork/test/address.wsdl'.

stderr: log4j:WARN No appenders could be found for logger (org.jboss.fuse.wsdl2rest.impl.WSDLProcessorImpl).

stderr: log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

wsdl2rest generated artifacts successfully

让这个东西等待的秘诀是什么?我很肯定我遗漏了一些明显的东西,但我主要是 Java 程序员而不是 JavaScript 并且在语言的一些异步方面有点挣扎。

提前致谢!

更新:虽然有人建议我使用 Mocha 的异步代码选项 (https://mochajs.org/#asynchronous-code),但我很难将这些概念融入我编写的测试中,如果有人有,我可以使用一些额外的帮助通过 Yeoman 生成器测试解决了这个问题?

@tbking 提供了正确的方法。这很好用 - 感谢有用的提示!

it('Should create the basic structure two ways', function () {
  basicProps.name = 'MyAppMock';
  basicProps.package = 'com.generator.mock';
  basicProps.camelVersion = '2.18.2';
  basicProps.camelDSL = 'spring';
  var wsdlPath = path.join(__dirname, '../test/address.wsdl');
  basicProps.wsdl = wsdlPath;
  basicProps.outdirectory = 'src/main/java';

  return helpers.run(path.join(__dirname, '../app'))
    .inTmpDir(function (dir) {
      var done = this.async(); // `this` is the RunContext object.
      fs.copy(path.join(__dirname, '../templates'), dir, done);
      basicProps.outdirectory = path.join(dir, 'src/main/java');
    })
    .withOptions({ wsdl2rest: true })
    .withPrompts({ name: basicProps.name })
    .withPrompts({ camelVersion: basicProps.camelVersion })
    .withPrompts({ camelDSL: basicProps.camelDSL })
    .withPrompts({ package: basicProps.package })
    .withPrompts({ wsdl: basicProps.wsdl })
    .withPrompts({ outdirectory: basicProps.outdirectory })
    .toPromise().then(function(value) {
      it('Should create the basic structure two ways', function () {
        console.log('testing...');
        assert.file('pom.xml');
        assert.file('README.md');
        assert.file('src/main/resources/META-INF/spring/camel-context.xml');
        assert.file('src/main/resources/META-INF/spring/camel-context-rest.xml')
      });
    });
});

在此处查看 mocha 文档 - https://mochajs.org/#asynchronous-hooks

您似乎需要将 "before" 放在 "describe" 之外。或者,您可以将 "it" 包装在另一个 "describe".

感谢@Evan,我们昨天找到了解决方案...

有两个部分 - 一个是我们创建的实际调用 Java jar 的方法没有返回 Promise...所以我们将其更改为:

   console.log('calling: ' + cmdString);
return new Promise((resolve, reject) => {
    const wsdl2rest = exec(cmdString);
    wsdl2rest.stdout.on('data', function (data) {
        console.log(`stdout: ${data}`);
    });
    wsdl2rest.stderr.on('data', function (data) {
        console.log(`stderr: ${data}`);
    });
    wsdl2rest.on('close', function (code) {
        if (code === 0) {
            console.log(`wsdl2rest generated artifacts successfully`);
            resolve()
        } else {
            reject()
            console.log(`stderr: ${code}`);
            console.log(`wsdl2rest did not generate artifacts successfully - please check the log file for details`);
        }
    });    
})

我们将测试更改为:

describe('generator-camel:wsdl2rest', function () {
  describe('Should properly scaffold with config for Spring and wsdl2rest', function () {
    it('Should create the basic structure two ways', function () {
      basicProps.name = 'MyAppMock';
      basicProps.package = 'com.generator.mock';
      basicProps.camelVersion = '2.18.2';
      basicProps.camelDSL = 'spring';
      var wsdlPath = path.join(__dirname, '../test/address.wsdl');
      basicProps.wsdl = wsdlPath;
      basicProps.outdirectory = 'src/main/java';
      return helpers.run(path.join(__dirname, '../app'))
        .inTmpDir(function (dir) {
          var done = this.async(); // `this` is the RunContext object.
          fs.copy(path.join(__dirname, '../templates'), dir, done);
          basicProps.outdirectory = path.join(dir, 'src/main/java');
        })
        .withOptions({ wsdl2rest: true })
        .withPrompts({ name: basicProps.name })
        .withPrompts({ camelVersion: basicProps.camelVersion })
        .withPrompts({ camelDSL: basicProps.camelDSL })
        .withPrompts({ package: basicProps.package })
        .withPrompts({ wsdl: basicProps.wsdl })
        .withPrompts({ outdirectory: basicProps.outdirectory })
        .toPromise() 
        .then(() => { 
          assert.file('pom.xml'); 
          assert.file('README.md'); 
          assert.file('src/main/resources/META-INF/spring/camel-context.xml'); 
          assert.file('src/main/resources/META-INF/spring/camel-context-rest.xml')
        });
    });
});

有了所有这些,我们就可以 运行 toPromise 并等待执行断言。

感谢Evan的指导!