Keming
Keming

Reputation: 253

Mocha flow control after assertion fails

I think mocha stops running the current test case after assertion fails, like this

it('test', function(done) {
    a.should.equal(b);
    //if a is not equal to be, won't go here
    //do something
    done();
}

I need to continue doing something after assertion fails, I tried to use try...catch, but there is no "else" for catch, so if I do

try {
    a.should.equal(b)
} catch(e) {
    console.log(e)
    done(e)
} finally {
    //do something
    done()
}

this will call done() twice, so I have to add a flag,

var flag = true;
try {
    a.should.equal(b)
} catch(e) {
    console.log(e)
    flag = false
    done(e)
} finally {
    //do something
    if(flag)
        done()
}

I think this is so complicated, so I wonder if there is an easier way to do it?

Upvotes: 1

Views: 2572

Answers (4)

jmr85
jmr85

Reputation: 51

The test runner's job to decide if it should bail or continue to test the other tests in the suite. If you want tests to continue running remove the --bail from your mocha.opts https://mochajs.org/api/mocha

Upvotes: 0

robertklep
robertklep

Reputation: 203519

An after hook will still get called when a test fails, so you can place your test inside a context that has such a hook:

describe('suite', function() {

  after(function(done) {
    // do something
    done();
  });

  it('test', function(done) {
    a.should.equal(b);
    done();
  }

});

Upvotes: 1

Alejandro Rivero
Alejandro Rivero

Reputation: 38

Remember the finally will be executed either it fails or doesn't fail. That is why it executes the done twice.

You can do:

    try {
        a.should.equal(b)
    } catch(e) {
        console.log(e)
        done(e)
    } 
    done()

If it fails you will exit through the catch, otherwise you keep going and return normally.

Upvotes: 0

doublesharp
doublesharp

Reputation: 27687

The reason it is being called twice is because the catch is handling the exception, but the finally block will always execute regardless of if the assertion throws an error.

Use return to handle your scenario - if an exception is caught it will return done with the error, otherwise it will skip the catch and just return done().

try {
    // test assertion
    a.should.equal(b)
} catch(e) {
    // catch the error and return it
    console.log(e)
    return done(e)
}
// just return normally
return done()

If you need to use it in an if/else scenario you can handle it with a variable.

var theError = false;
try {
    // test assertion
    a.should.equal(b)
} catch(e) {
    // indicate we caught an error
    console.log(e)
    theError = e
}

if (theError) {
    // there was an exception
    done(theError)
} else {
    // no exceptions!
    done()
}

Upvotes: 0

Related Questions