Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Mocha know to wait and timeout only with my asynchronous tests?

When I'm testing with Mocha, I often have a combination of both asynchronous and synchronous tests that need to run.

Mocha handles this beautifully allowing me to specify a callback, done, whenever my tests are asynchronous.

My question is, how does Mocha internally observe my tests and know that it should wait for asynchronous activity? It seems to wait anytime I have the callback parameter defined in my test functions. You can see in the examples below, the first test should timeout, the second should proceed and finish before user.save calls the anonymous function.

// In an async test that doesn't call done, mocha will timeout.
describe('User', function(){
  describe('#save()', function(){
    it('should save without error', function(done){
      var user = new User('Luna');
      user.save(function(err){
        if (err) throw err;
      });
    })
  })
})

// The same test without done will proceed without timing out.
describe('User', function(){
  describe('#save()', function(){
    it('should save without error', function(){
      var user = new User('Luna');
      user.save(function(err){
        if (err) throw err;
      });
    })
  })
})

Is this node.js specific magic? Is this something that can be done in any Javascript?

like image 477
Paul English Avatar asked Nov 26 '12 17:11

Paul English


People also ask

How do you test async in Mocha?

Writing Asynchronous Tests with Mocha. To indicate that a test is asynchronous in Mocha, you simply pass a callback as the first argument to the it() method: it('should be asynchronous', function(done) { setTimeout(function() { done(); }, 500); });

Do Mocha tests run sequentially?

According to it, tests are run synchronously. This only shows that ordered code is run in order. That doesn't happen by accident.

Do Mocha tests run in parallel?

Mocha does not run individual tests in parallel. If you only have one test file, you'll be penalized for using parallel mode.

How do I change the default timeout on my Mocha?

In case anyone is interested, most IDEs also allow you to inject mocha options for test execution; e.g. for WebStorm, you can enter this (i.e. "--timeout 10000") under Run->Edit Configurations->Extra Mocha Options.


2 Answers

This is simple pure Javascript magic.

Functions are in fact objects, and they have properties (such as the number of parameters are defined with the function).

Look at how this.async is set in mocha/lib/runnable.js

function Runnable(title, fn) {
  this.title = title;
  this.fn = fn;
  this.async = fn && fn.length;
  this.sync = ! this.async;
  this._timeout = 2000;
  this._slow = 75;
  this.timedOut = false;
}

Mocha's logic changes based whether or not your function is defined with parameters.

like image 186
supershabam Avatar answered Sep 24 '22 19:09

supershabam


What you're looking for is Function's length property which can tell how many arguments a function is expecting. When you define a callback with done it can tell and treats it asynchonously.

function it(str, cb){
  if(cb.length > 0)
    //async
  else
    //sync
}

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/Length

like image 41
George Avatar answered Sep 25 '22 19:09

George