Question

I have an async function that returns a callback with a status code and path if successful. I would like to use jasmine to test that I receive that status code and have the path be assigned to all future tests. I keep getting an undefined value for my tests...

function make_valid(cb){
    var vdt = child.spawn('node', base,
        {cwd: ims_working_dir, stdio: ['pipe', 'pipe', 'pipe']},
        function (error, stdout, stderr) {
            if (error !== null) {
                console.log('spawn error: ' + error);
            }
        });
    vdt.stdout.setEncoding('utf8');
    vdt.stdout.on('data', function(data) {});

    vdt.on('close', function(code) {

        if (code === 0) {
            cb(null, '/home/');
        } else {
            cb(null, code);
        }
    });
}

describe("IMS", function(cb) {
    var path;
    jasmine.getEnv().defaultTimeoutInterval = 40000;

    beforeEach(function(done, cb) {
        console.log('Before Each');
        path = make_valid(cb);
        done();
    });

    it("path should not be null", function() {
        expect(path).toBeDefined();
    });
});

Here is the output:

Failures:

  1) IMS path should not be null
   Message:
     Expected undefined to be defined.
   Stacktrace:
     Error: Expected undefined to be defined.
    at null.<anonymous> (/home/evang/Dev/dataanalytics/IMS_Tester/spec/ims-spec.js:46:16)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Finished in 0.014 seconds

1 test, 1 assertion, 1 failure, 0 skipped

If i get the path passed in the beforeEach declaration I want to write more tests where I parse the file. I think I am dealing with the callbacks incorrectly or maybe I need to use a spy. Let me know!

Was it helpful?

Solution

You are setting path with the return value of the make_valid function, yet that function returns nothing.

When I've used jasmine, I had success with the done() callbacks only for the tests themselves (the it() functions).

When needing an asynchronous function before each test, I used their runs() and waitsFor() functions.

Try some code like this (modified for your example):

var code = null;
beforeEach( function() {
  // get a token so we can do test cases. async so use jasmine's async support
  runs( function() {
    make_valid( function( error, returnCode ) {
      if( error ) code = "ERROR_CODE";
      else code = returnCode;
    } );
  } );

  waitsFor( function() {
    return code !== null;
  } );

  runs( function() {
    expect( code ).toBeDefined();
  } );
} );

afterEach( function() {
  code = null;
} );

EDIT: Based on our comments, a suggested approach for a one-time asynchronous test that applies to other tests down the line would be this sample-spec.js. The inner tests will not pass if the outer it() does not use done().

/*jslint node: true */
"use strict";

describe( "The full, outer test", function() {

  var code = null;
  it( "should setup for each inner test", function(done) {
    make_valid( function( error, returnCode ) {
      expect( returnCode ).toBeDefined();
      code = returnCode;
      done();
    } );
  } );

  describe( "The inner tests", function() {
    it( "inner test1", function() {
      expect( code ).not.toBeNull();
    } );
    it( "inner test2", function() {
      expect( code ).toBe(200);
    } );
  } );
} );

function make_valid( callback ) {
  setTimeout( function(){ callback( null, 200 ); }, 500 );
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top