Home > OS >  Converting a mocha "done()" test to "async" when "done()" is called in
Converting a mocha "done()" test to "async" when "done()" is called in

Time:03-02

I would like to add a call to a sync function to the test below:

describe('the server', function() {
  it('should respond to a udp packet', function(done) {

    // TODO: call async function here

    const udp = dgram.createSocket('udp4');

    udp.on('error', function(error) {
      console.log(error);
    });

    udp.on('message', function(msg, rinfo) {
      console.log('msg', msg);
      console.log('rinfo', rinfo);
      // TODO: check the reply
      udp.close();
      done();
    });
    udp.bind();

    // send a request
    const bytes = Buffer.from("421a0800117860bc457f0100001a0653455256455222054d54303031", 'hex');
    udp.send(bytes, SERVER_PORT, SERVER_ADDR)
  });
});

If I just add async, to make:

it('should respond to a udp packet', async function(done) { 

I get an error:

1) the server
     should respond to a udp packet:
   Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

but I need the done as the test is only over when a packet is received from the server.

Is there a way of only "returning" from an async function from within an inner function?

CodePudding user response:

There are at least two approaches here: work with the promise returned by the async call or make the whole test function async. I'm going to show the second method becuase it's easier to implement without knowing how the async function call in the todo looks like.

There are basically three changes to be done:

  • Make the test function async and remove the done parameter.
  • Wrap the statement or group of statements that use the done callback in a promise. Name the first parameter of the promise callback done if you want to keep that name.
  • return the promise.
describe('the server', function() {
  it('should respond to a udp packet', async function() {

    // TODO: call async function here

    const udp = dgram.createSocket('udp4');

    udp.on('error', function(error) {
      console.log(error);
    });

    const promise = new Promise(done => {
      udp.on('message', function(msg, rinfo) {
        console.log('msg', msg);
        console.log('rinfo', rinfo);
        // TODO: check the reply
        udp.close();
        done();
      });
    });

    udp.bind();

    // send a request
    const bytes = Buffer.from("421a0800117860bc457f0100001a0653455256455222054d54303031", 'hex');
    udp.send(bytes, SERVER_PORT, SERVER_ADDR);
    return promise;
  });
});

This should be sufficient for a test. For a more accurate error handling you may want to reject the promise in case of an exception:

const promise = new Promise((done, reject) => {
    try {
      udp.on('message', function(msg, rinfo) {
      console.log('msg', msg);
      console.log('rinfo', rinfo);
      // TODO: check the reply
      udp.close();
    } catch (err) {
      reject(err);
      return;
    }
    done();
  });
});
  • Related