1

In my mocha-test suite, I want to test a functionality which makes a asynchronous call behind the scene. How can I wait until the asynchronous call has finished ?

For example, I make two back to back post calls. The first post call also makes an asynchronous call internally, until that asynchronous operation is complete the second post call won't pass.

I need either of below:

1) to put a delay between the two post calls so that to make sure the asynchronous part in the first post is complete.
2) to make the second post call repetitively until it passes.
3) or how to test out the asynchronous call through mocha-chai ?

Below is the example:

describe('Back to back post calls with asynchronous operation', ()=> {

            it('1st and 2nd post', (done) => {
                chai.request(server)
                .post('/thisis/1st_post')
                .send()
                .end((err, res) => {
                 expect(res.statusCode).to.equal(200);

                 /* HERE I Need A Delay or a way to call                   
               the below post call may be for 5 times */                       

                 chai.request(server)
                .post('/thisis/second_post')
                .send()
                .end((err, res) => {
                 expect(res.statusCode).to.equal(200);


                });

                done();
                });
            });         

        });

Is there a way to handle this ? Please help.

Thanks.

1 Answers1

2

In order to test an asynchronous function with mocha you have the following possibilities

use done only after the last callback in your sequence was executed

it('1st and 2nd post', (done) => {
  chai.request(server)
    .post('/thisis/1st_post')
    .send()
    .end((err, res) => {
      expect(res.statusCode).to.equal(200);

      /* HERE I Need A Delay or a way to call
    the below post call may be for 5 times */

      chai.request(server)
        .post('/thisis/second_post')
        .send()
        .end((err, res) => {
          expect(res.statusCode).to.equal(200);

          //call done only after the last callback was executed
          done();
        });
    });
});

use done callback with promises

describe('test', () => {
  it('should do something async', (done) => {
    firstAsyncCall
       .then(() => {
          secondAsyncCall()
            .then(() => {
              done() // call done when you finished your calls
            }
       })
  });
})

After a proper refactor you will get something like

describe('test', () => {
  it('should do something async', (done) => {
    firstAsyncCall()
      .then(secondAsyncCall())
      .then(() => {
        // do your assertions
        done()
      })
      .catch(done)
  })
})

use async await, much cleaner

describe('test', () => {
  it('should do something async', async () => {
    const first = await firstAsyncCall()
    const second = await secondAsyncCall()

    // do your assertion, no done needed
  });
})

An other moment to keep in mind is the --timeout argument when running mocha tests. By default mocha is waiting 2000 miliseconds, you should specify a larger amount when the server is responding slower.

mocha --timeout 10000

Alexandru Olaru
  • 5,860
  • 4
  • 21
  • 48
  • I do not have any function like firstAsyncCall() and secondAsyncCall(). I just have to make two post calls through the routes. As I said the first post call completes and returns to the callback , however in the background some other async call takes place. So when the second post call takes place inside the callback of the first post call, the async function which runs behind is not finished. So I just need a break/time delay before the second post starts. May be I want the second post call to happen 3-4 times before I assert it as pass/fail. – A.G.Progm.Enthusiast Mar 09 '18 at 17:26
  • You may also assume that there are some more post/get/pull call chain before and after the two post calls I have shown. Only these two post calls need to have a time delay between them. – A.G.Progm.Enthusiast Mar 09 '18 at 17:27
  • Could you please show if I can put the second post call in a function and keep calling that function in a loop until I get the desired result ? Not sure how is this async await works. – A.G.Progm.Enthusiast Mar 10 '18 at 14:17
  • Any help on this question how to test asynchronous endpoint will be much appreciated. – A.G.Progm.Enthusiast Mar 10 '18 at 20:06
  • Can you please add the code for the test that you added, it will be easier in this way to help you. – Alexandru Olaru Mar 12 '18 at 06:55