简体   繁体   English

Mocha / Sinon - 在ES6 Promise中使用child_process.exec进行单元测试/存根功能

[英]Mocha / Sinon - Unit testing / stubbing function with child_process.exec inside ES6 Promise

I have a function that returns an ES6 promise for use in another external promise chain. 我有一个函数返回ES6承诺,用于另一个外部promise链。 The function scans for wifi networks using child_process.exec. 该功能使用child_process.exec扫描wifi网络。 The output from exec is sent via the callback to a synchronous parsing function that will return the output in a formatted object, and then resolve the outer promise: exec的输出通过回调发送到同步解析函数,该函数将返回格式化对象中的输出,然后解析外部promise:

var exec = require('child_process').exec;

function scan() {
    return new Promise((resolve, reject) => {

        // getCurrent returns a promise
        getCurrent().then(network => {
            exec('iwlist wlan0 scan', function(err, stdout, stderr) {
                (err) ? reject(stderr) : resolve(parseOutput(stdout, network));                 
            });
        })
        .catch(err => {
            reject(err);
        }); 
    }); 
}

The problem is, I can't seem to get sinon stubs working properly to get the stubbed version of exec to be called. 问题是,我似乎无法使sinon存根正常工作以获得被调用的exec版本。 Currently I have something along the lines of: 目前我有以下几点:

var wifi = require('./wifi');

describe('#scan', function() {

    it('Should scan and return networks object', function() {

        var fakeNetwork = '(fake iwlist output goes here)';  
        var exec = sinon.stub(child_process, 'exec').yields(false, fakeNetwork);
        var getCurrent = sinon.stub(wifi, 'getCurrent').returns(Promise.resolve('current-ssid'));

        wifi.scan().then(function(networks) {
            console.log(networks);
            sinon.assert.calledOnce(getCurrent);
            sinon.assert.calledOnce(exec);
        });

        getCurrent.restore();
        exec.restore();

    });
});

I have also tried stubbing like: 我也尝试过像:

var getCurrent = sinon.stub(wifi, 'getCurrent', function() {
    return Promise.resolve('current-ssid').then(network => {
        exec('iwlist wlan0 scan', function(err, data) {
            return(wifi.parseOutput(data, network));                
        });
    });
});

The behavior seems to be that either exec never gets called, or more strangely, that the stubbed exec does get called, but the 'real' functions get called anyway. 行为似乎是exec永远不会被调用,或更奇怪的是,被调用的exec被调用,但无论如何都会调用'真正的'函数。

With all of the stubs, all I am really "testing" is the parseOutput method, so should I just ditch testing the 'scan' function completely and only focus on the parse function (which would be simple to test), or is there another way I should be looking at this? 对于所有的存根,我真正“测试”的是parseOutput方法,所以我应该完全抛弃测试'scan'函数并且只关注解析函数(这将很容易测试),或者是否有另一个我应该看看这个吗?

I believe I am just doing something obviously wrong, and have been hitting a wall here for several hours. 我相信我只是在做一些明显错误的事情,而且已经在这里打了几个小时。 I'm hoping someone has run into this before and can suggest an alternative/better approach. 我希望有人之前遇到过这种情况,可以建议一种替代/更好的方法。

you can use stub.yields([arg1, arg2, ...]) sinon stubs guide 你可以使用stub.yields([arg1,arg2,...]) sinon stubs guide

here is my code 这是我的代码

function getVersioniList() {
    let versionList = new Promise((resolve, reject) => {
        child_process.exec(cmd, function(error, stdout, stderr) {
            if (error) {
                reject(error);
            }
            resolve(stdout);
        });
    });

    return versionList;
}

and unit test code as below 和单元测试代码如下

// i like the sandbox, or you can use sinon itself
sandbox = sinon.sandbox.create();
sandbox.stub(child_process, 'exec').yields(undefined, [1, 2, 3]);

assert.equal(await getVersioniList(), [1, 2, 3]);

finally, you can get versionList [1, 2, 3] 最后,你可以得到versionList [1,2,3]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM