R.A. Lucas
R.A. Lucas

Reputation: 1151

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!

Upvotes: 25

Views: 64629

Answers (6)

David Corral
David Corral

Reputation: 4145

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.

Upvotes: 15

Flops
Flops

Reputation: 1420

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);
 });

Upvotes: 29

ymz
ymz

Reputation: 6916

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)

Upvotes: 5

Jeff Lowery
Jeff Lowery

Reputation: 2597

Here's another, using promises:

it('go, then stop', (done) => {
// this.skip();
go()
  .then((response) => { console.log('go was called'); return response; })
  .then(response => response.should.equal('acknowledged'))
  .then(() => new Promise(resolve => setTimeout(() => { resolve(); }, 3000)))
  .then(() => console.log('3 second wait is over'))
  .then(() => stop())
  .then(response => response.should.equal('acknowledged'))
  .then(() => done());
  }).timeout(15000);

Upvotes: 1

Emre Tapcı
Emre Tapcı

Reputation: 1908

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.

Upvotes: 0

Zlatko
Zlatko

Reputation: 19569

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.

Upvotes: 10

Related Questions