Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Mocha wait before running next test

I've got some mocha tests that require data from prior function calls. However, because my code is using a web service, I would like it to wait for a predetermined amount of time before running the next test.

Something like this:

var global;

it('should give some info', function(done) {
  run.someMethod(param, function(err, result) {
    global = result.global
  done();
  });
});

wait(30000); // basically block it from running the next assertion

it('should give more info', function(done) {
  run.anotherMethod(global, function(err, result) {
    expect(result).to.be.an('object');
  done();
  });
});

Any ideas would be appreciated. Thanks!

like image 703
R.A. Lucas Avatar asked Aug 27 '14 22:08

R.A. Lucas


People also ask

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.

Can Mocha rerun tests?

Retrying Mocha tests Mocha provides a this. retries() function that allows you specify the number of times a failed test can be retried. For each retry, Mocha reruns the beforeEach() and afterEach() Hooks but not the before() and after() Hooks.

How do you skip the Mocha test?

This inclusive ability is available in Mocha by appending . skip() to the suite or to specific test cases. The skipped tests will be marked as "pending" in the test results.

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.


Video Answer


5 Answers

setTimeout definitely could help, but there may be a "cleaner" way to do it.

The documentation here actually says to use this.timeout(delay) to avoid timeout errors while testing async code, so be careful.

var global;

it('should give some info', function(done) {
  run.someMethod(param, function(err, result) {
    global = result.global
  done();
  });
});

it('should give more info', function(done) {
    this.timeout(30000);

    setTimeout(function () {
      run.anotherMethod(global, function(err, result) {
        expect(result).to.be.an('object');
        done();
      });
    }, 30000);
 });
like image 180
Flops Avatar answered Oct 19 '22 15:10

Flops


While this.timeout() will extend the timeout of a single test, it's not the answer to your question. this.timeout() sets the timeout of your current test.

But don't worry, you should be fine anyway. Tests are not running in parallel, they're done in series, so you should not have a problem with your global approach.

like image 34
Zlatko Avatar answered Oct 19 '22 13:10

Zlatko


In my case, I was coding a RESTful API in NodeJS that was manipulating some files locally. As I was launching the tests, the API was receiving multiple requests and it makes my API manipulate, concurrently, these files in the machine, which led me to a problem.

So, I needed to put some time (1 sec was enough) between these API calls. For me, the solution was the following one:

beforeEach( async () => {
   await new Promise(resolve => setTimeout(resolve, 1000));
   console.log("----------------------");
});

Now, before each it() test, the previous function is run, and I have a sleep of 1 second between API calls.

like image 10
David Corral Avatar answered Oct 19 '22 13:10

David Corral


First:

This thread has great answers! I personally Liked @Flops answer (got my upvote)

Second:

To clarify this (as much as possible) here is a code sample very similar to the one I ended up with (tested and verified)

function delay(interval) 
{
   return it('should delay', done => 
   {
      setTimeout(() => done(), interval)

   }).timeout(interval + 100) // The extra 100ms should guarantee the test will not fail due to exceeded timeout
}

it('should give some info', function(done) {
  run.someMethod(param, function(err, result) {
    global = result.global
  done();
  });
});

delay(1000)

it('should give more info', function(done) {
  run.anotherMethod(global, function(err, result) {
    expect(result).to.be.an('object');
  done();
  });
});

Side note: you can also use delay functions one after another and still preserve consistency (tests order)

like image 5
ymz Avatar answered Oct 19 '22 13:10

ymz


First of all, for proper unit testing, you should never need some sleep between tests. If you do need a sleep, this means the functions you are testing require a delay before completing its expected task, which must be handled inside that function, with some asynchronous wait or sleep. Upon exit from a function, its lifetime must end and the expected result must be acquired immediately.

like image 1
Emre Tapcı Avatar answered Oct 19 '22 15:10

Emre Tapcı