Search code examples
javascriptnode.jseventschaisinon

Unit testing an Exec stdout event NodeJS


I have below code.

//utils.js
const cp = require('child_process');

module.exports.execuateBashCommand = ()=> {
    return new Promise((resolve, reject)=> {
        try {
            cp.exec('bash bash.sh').stdout.on('data', (response)=> {
                if (response.toString().indexOf("Success") > -1) {
                    //Some business logic
                    const result = "working";
                    resolve(result);
                }
            });
        } catch (error) {
            console.log("Error", error);
            reject(error);
        }
    })
}

Here, there is an anonymous function that gets fired when a data event is emitted by stdout of exec process. I have no control over the output of bash.js, the desired response may take 5 to 10 seconds. Also I cannot add a timer and wait for this event to fire as I have mocked the exec response using sinon. So there is no real call to bash.js. So how can I emit this event manually and see if the business logic get computed? I am new to unit testing in Javascript. Currently I am using mocha and sinon for my unit testing requirements.

I have following test case, but it is not working as expected..

//utils.test.js
 it("1. test case", (done)=> {
        try {
            const mockStdout = new events.EventEmitter();
            mockStdout.on('data', ()=> {
                return "Success";
            });
            mockStdout.emit('data');
            sandbox.stub(cp.exec('test test'), 'stdout').returns(mockStdout);
            utils.execuateBashCommand().then((result)=> {
                assert(data, "working");
                done();
            });
        } catch (error) {
            console.log("Error in test cases: ", error);
        }
    })

Please advice.


Solution

  • I have tried couple of things. Finally, my test cases got passed by below solution.

    it("1. test case", (done) => {
                const fake = {
                    stdout: new EventEmitter(),
                }
                fake.stdout.on('data', () => { });
                sinon.stub(cp, 'exec').returns(fake);
                utils.execuateBashCommand().then((res) => {
                    expect(res, true);
                    done();
                });
                fake.stdout.emit('data', "Success");
        })
    

    I am not sure whether this is a right way or not. If anyone have better solution, please advice.