![](/img/trans.png)
[英]How to provide the password for Spawn Child_Process in Node.js
[英]How to mock the Node.js child_process spawn function?
有沒有一種簡單的方法來模擬 Node.js child_process spawn
函數?
我有如下代碼,並希望在單元測試中對其進行測試,而不必依賴實際的工具調用:
var output;
var spawn = require('child_process').spawn;
var command = spawn('foo', ['get']);
command.stdout.on('data', function (data) {
output = data;
});
command.stdout.on('end', function () {
if (output) {
callback(null, true);
}
else {
callback(null, false);
}
});
是否有(經過驗證和維護的)庫允許我模擬spawn
調用並讓我指定模擬調用的輸出?
我不想依賴工具或操作系統來保持測試的簡單和隔離。 我希望能夠運行測試而不必設置復雜的測試裝置,這可能意味着很多工作(包括更改系統配置)。
是否有捷徑可尋?
你可以使用sinon.stubs sinon stubs 指南
// i like the sandbox, or you can use sinon itself
let sandbox = sinon.sandbox.create();
let spawnEvent = new events.EventEmitter();
spawnEvent.stdout = new events.EventEmitter();
sandbox.stub(child_process, 'spawn').returns(spawnEvent);
// and emit your event
spawnEvent.stdout.emit('data', 'hello world');
console.log(output) // hello world
遇到了這個問題,nwinkler 的回答讓我走上了正軌。 下面是一個 Mocha、Sinon 和 Typescript 示例,它將 spawn 包裝在一個 Promise 中,解析退出代碼是否為零,否則拒絕,它收集 STDOUT/STDERR 輸出,並讓您通過 STDIN 輸入文本。 測試失敗只是測試異常的問題。
function spawnAsPromise(cmd: string, args: ReadonlyArray<string> | undefined, options: child_process.SpawnOptions | undefined, input: string | undefined) {
return new Promise((resolve, reject) => {
// You could separate STDOUT and STDERR if your heart so desires...
let output: string = '';
const child = child_process.spawn(cmd, args, options);
child.stdout.on('data', (data) => {
output += data;
});
child.stderr.on('data', (data) => {
output += data;
});
child.on('close', (code) => {
(code === 0) ? resolve(output) : reject(output);
});
child.on('error', (err) => {
reject(err.toString());
});
if(input) {
child.stdin.write(input);
child.stdin.end();
}
});
}
// ...
describe("SpawnService", () => {
it("should run successfully", async() => {
const sandbox = sinon.createSandbox();
try {
const CMD = 'foo';
const ARGS = ['--bar'];
const OPTS = { cwd: '/var/fubar' };
const STDIN_TEXT = 'I typed this!';
const STDERR_TEXT = 'Some diag stuff...';
const STDOUT_TEXT = 'Some output stuff...';
const proc = <child_process.ChildProcess> new events.EventEmitter();
proc.stdin = new stream.Writable();
proc.stdout = <stream.Readable> new events.EventEmitter();
proc.stderr = <stream.Readable> new events.EventEmitter();
// Stub out child process, returning our fake child process
sandbox.stub(child_process, 'spawn')
.returns(proc)
.calledOnceWith(CMD, ARGS, OPTS);
// Stub our expectations with any text we are inputing,
// you can remove these two lines if not piping in data
sandbox.stub(proc.stdin, "write").calledOnceWith(STDIN_TEXT);
sandbox.stub(proc.stdin, "end").calledOnce = true;
// Launch your process here
const p = spawnAsPromise(CMD, ARGS, OPTS, STDIN_TEXT);
// Simulate your program's output
proc.stderr.emit('data', STDERR_TEXT);
proc.stdout.emit('data', STDOUT_TEXT);
// Exit your program, 0 = success, !0 = failure
proc.emit('close', 0);
// The close should get rid of the process
const results = await p;
assert.equal(results, STDERR_TEXT + STDOUT_TEXT);
} finally {
sandbox.restore();
}
});
});
對於仍然遇到此特定問題的任何人,出於某種原因,其他答案中的建議無濟於事,我能夠通過替換來使其與proxyrequire
( https://github.com/thlorenz/proxyquire ) 一起使用真正的 child_process 產生了一個事件發射器,然后我在我的測試中使用它來模擬發射。
var stdout = new events.EventEmitter();
var stderr = new events.EventEmitter();
var spawn = new events.EventEmitter();
spawn.stderr = stderr;
spawn.stdout = stdout;
var child_process = {
spawn: () => spawn,
stdout,
stderr
};
// proxyrequire replaces the child_process require in the file pathToModule
var moduleToTest = proxyquire("./pathToModule/", {
'child_process': child_process
});
describe('Actual test', function () {
var response;
before(function (done) {
// your regular method call
moduleToTest.methodToTest()
.then(data => {
response = data;
done();
}).catch(err => {
response = err;
done();
});
// emit your expected response
child_process.stdout.emit("data", "the success message sent");
// you could easily use the below to test an error
// child_process.stderr.emit("data", "the error sent");
});
it('test your expectation', function () {
expect(response).to.equal("the success message or whatever your moduleToTest
resolves with");
});
});
希望這可以幫助...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.