私はnodejsを学んでいて、実際には意図したとおりに機能するように見えるshelljs関数用のこのラッパーを書きました。
/**
* Wrapper for Shelljs.exec to always return a promise
*
* @param {String} cmd - bash-compliant command string
* @param {String} path - working directory of the process
* @param {Object} _shell - alternative exec function for testing.
* @returns {String}
* @throws {TypeError}
*/
function shellExec(cmd, path, _shell = shelljs){
if( typeof _shell.exec !== "function") throw new TypeError('_shell.exec must be a function');
return new Promise((resolve, reject) => {
let options = { cwd: path, silent: true, asyc: true }
// eslint-disable-next-line no-unused-vars
return _shell.exec(cmd, options, (code, stdout, stderr) => {
// shelljs.exec does not always return a code
if(stderr) {
return reject(stderr);
}
return resolve(stdout);
});
});
}
ただし、単体テストを試みると、関数がタイムアウトします。テストでの非同期コード、約束、または非同期/待機に関するmochajsドキュメントを読みました。私が知っている約束を返すシノンフェイクを使いたいです。Mocha は、関数が error を介して promise を返していないことがエラーであると教えてくれましたError: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves
。偽物を不適切に作成したと思いますが、他にどのようにしてこれを行うべきだったのかわかりません。
const { expect, use } = require('chai');
const sinon = require('sinon');
const sinonChai = require("sinon-chai");
const utils = require('../utility/exec');
use(sinonChai);
it('sinon fake should resolve', async () =>{
const fake = sinon.fake.resolves('resolved');
const result = await fake();
expect(result).to.equal('resolved');
});
describe('Utility Functions', () =>{
describe('shellExec', () =>{
it('should accept an alternate execute function', async () =>{
const fakeShell = { exec: sinon.fake.resolves('pass') };
const result = await utils.shellExec('pwd', 'xyz', fakeShell);
expect(result).to.equal('pass');
expect(fakeShell.exec).to.have.been.calledOnce;
});
});
});