Search code examples
node.jsjasmine-node

node child process jasmine error


I get the error below when trying to execute jasmine-node test.

I am trying to test the following javascript

var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');

Nndb = function(child_process) {
    this.child_process = child_process;
};

Nndb.prototype.invokePhantomProcess = function( phantomScriptToRun, offSet) {

    var child =  this.child_process.spawn('phantomjs', [phantomScriptToRun, offSet]);
    child.stdout.on('data',function(data){

        console.log(decoder.write(data));

    });

    child.stderr.on('data', function (data) {
        console.log('stderr: ' + data);
    });

    child.on('exit', function (code) {
        console.log('child process exited with code ' + code);
    });

    return 0;

};

exports.Nndb = Nndb;

with the following test spec:

require('../src/TDDQuestion.js');

describe("Verify", function() {

    it("spawns child process", function() {

        var stdout = {
            on: function() {}
        };

        var child_process = {
            stdout: stdout,
            spawn: function(){return this;}
        };

        spyOn(child_process,"spawn").andReturn(child_process);
        spyOn(child_process, "stdout").andReturn(stdout);

        var nndb = new Nndb(child_process);

        nndb.invokePhantomProcess('../src/TDDQuestion.js', 0);
        expect(child_process.spawn).toHaveBeenCalledWith( 'phantomjs',['../src/TDDQuestion.js',0]);

    });


});

and getting the error:

enter Stacktrace:
 TypeError: Object function () {
spyObj.wasCalled = true;
spyObj.callCount++;
var args = jasmine.util.argsToArray(arguments);
spyObj.mostRecentCall.object = this;
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({object: this, args: args});
return spyObj.plan.apply(this, arguments);
} has no method 'on'
    at Nndb.invokePhantomProcess

(/Users/.../src/TDDQuestion.js:11:18)
at null.<anonymous> (/Users/.../spec/TDDQuestionSpec.js:21:14)

I see the method 'on' is present in the object stdout in the test spec.

I also observed that when changing the line in TDDQuestion.js from

child.stdout.on //returns a function causing the error

to

child.stdout().on //returns the stdout object with the 'on' method

resolves the issue.


Solution

  • Removing the spying on stdout and treating it as a property (which it is) resolves the issue. Spying applies only to properties which are functions on a method.

    I am pasting the corrected TDDSpecQuestion.js here.

    require('../src/TDDQuestion.js');
    
    describe("Verify", function() {
    
        it("spawns child process", function() {
    
    
            var stdout = {
                on: function() {}
            };
            var stderr = {
                on: function() {}
            }
    
            var child_process = {
                stderr: stderr,
                stdout: stdout,
                spawn: function(){return this;},
                on: function(){}
            };
            debugger;
            spyOn(child_process,"spawn").andReturn(child_process);
            var nndb = new Nndb(child_process);
    
            nndb.invokePhantomProcess('../src/TDDQuestion.js', 0);
            expect(child_process.spawn).toHaveBeenCalledWith( 'phantomjs',['../src/TDDQuestion.js',0]);
    
        });
    
    
    });