2

I'm trying to create a test case with Mocha but my code is asynchronous.

That's fine, I can add a "done" callback function to "it" and that will work perfectly fine for positive cases. But when trying to test negative cases, it will just make the test fail.

I would like to make something like this but asynchronous:

someObject.someMethod(null).should.equal(false)

Instead I can only test for a callback to return, instead of testing what really happend (null is not valid):

it('this should return false or an error', function(done) {
    someObject.someMethod(null, '', done);
});

I would like to write something like this:

it('this should return false or an error', function(done) {
    someObject.someMethod(null, '', done).should.throw();
});

but that would lead to this error:

"TypeError: Cannot read property 'should' of undefined"

I also tried using expect and assert, but the same rules apply.

Any clues? Thanks

EDIT #1:

I've unsuccessfully tried:

Using true/false

return (true); // ok
retur (false); // error

Using callback:

callback(); // ok
callback(err); // error

Using callback2:

callback(true); // ok
callback(false); // error

Using callback3:

callback(null); // ok
callback(new Error()); // error

Using throw (also inside a try/catch block):

// a
 throw new Error();
callback();  

// b
 throw new Error();
callback(new Error());  

// c
 throw new Error();
callback(false);  

I have also tried several combinations such as returning and calling a callback, returning on success but throwing or calling a callback on error and conversely..

EDIT #2:

it('should throw', function(done) {
  (function(done) {
    someObject.someMethod(null, '', done)
  }).should.throw();
});`

EDIT #3:

To wrap up on the test-side:

it('this should return false or an error', function(done) {
    someObject.someMethod(null, function(err, value) {
        expect(value === false || err instanceof Error).toEqual(true);
       return done();
    });
}); 

And on the code-side: function(var, callback)

...
callback(new Error('your comments'), false);
// or
callback(new Error('your comments'));
...
// if successful:
callback();
// or
callback(null);
// or
callback(null, 'foo');
nico
  • 144
  • 12

2 Answers2

1

Assuming that someObject.someMethod adheres to the regular Node.js callback convention (error as first argument, value as second), you could use something like this:

it('this should return false or an error', function(done) {
  someObject.someMethod(null, '', function(err, value) {
    (err instanceof Error || value === false).should.equal(true);
    return done();
  });
});

I inferred from the name of the test case that you want to test for two situations: either the method is "returning" an error, or it's "returning" a value of false (by calling the callback function with the appropriate arguments).

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks this worked! I had to use a different syntax though, and now I can decide to use the convention or just return a value, while keeping the code asynchronous. – nico Jul 31 '15 at 22:24
  • I finally cleaned up the code and your syntax works perfectly fine. So either `(value === false || err instanceof Error).should.equal(true);` or `expect(value === false || err instanceof Error).toEqual(true);` work! – nico Jul 31 '15 at 22:39
0

You could wrap done in a anonymous function, and process (err,res) manually and call done with hard coded inputs. Or:

(function(){
  throw new Error('fail');
}).should.throw();
Hyo Byun
  • 1,196
  • 9
  • 18
  • I don't fully understand what you mean. I tried this without any improvements: (see edit#2) – nico Jul 31 '15 at 19:35