razi3lCast
razi3lCast

Reputation: 115

How to run async functions in before hook in MochaJS?

I try to call a lot of async functions in my mocha JS before hook but they are executed at last. Basically I am trying to execute repeated tests with different params from the constructor initialization.

I tried with only one function but it also execute at last.Tried to pass done() function to inner async function but it doesnt help either.

a.test.js and base.tests.js files :

describe('Test block', () => {
    before((done) => {
            const baseClass = new baseClass()
            baseTests.applyTests(done)
        });
    describe('test',()=>{
    ....first which should be executed;
    })
}
----------------------------------------------------------------
class baseClass {

    constructor() {
        init smth....
    }

    async applyTests(done) {
        await Promise.All(
        [
            a(),
            b(),
            c()
        ]
        done();
        )
    }
    async a() {
        return describe('TEST', () => {
            it('TEST', (done) => {
                chai.request(server)
                    .get(url)
                    .end((err, res) => {
                        asserts...
                        done();
                    });
            });
        }}

I expect to run first the async operations in the before hook and after that all other tests.

Upvotes: 0

Views: 1335

Answers (1)

Elliot Nelson
Elliot Nelson

Reputation: 11557

Keep in mind that describe and it blocks do not execute any tests; they add tests to the test list that Mocha will execute. Putting a describe block inside a function called from a before hook like this won't ever end up executing code like chai.request(... etc. (And even if it did, it would be totally broken: a before hook is run before each test, you don't want to do asserts there because it won't be linked to any particular unit test.)

I can't give more concrete advice because I'm not sure what you were trying to accomplish, but in general, your describe and it blocks should be top-level constructs and not put inside other code like this.

EDIT: Just to make the execution path here clear: your before hook runs, which calls applyTests, which calls a(), which executes a describe block and adds your unit test TEST to the test list, then it returns. It then begins running tests, including test and TEST.

EDIT: Ah, makes sense, let me suggest two patterns that are often used in unit tests.

Pattern 1: "Test Loop"

This pattern creates many similar-looking tests, using an array of input params to produce appropriate test descriptions and test bodies.

[
    { foo: "milk", bar: "smoothie" },
    { foo: "yogurt", bar: "fridge" },
    { foo: "whatever", bar: "container" }
].forEach(test => {
    it("puts the " + test.foo + " in the " + test.bar, function () {
        assert(subject.someMethod(foo) === bar);
    });
});

Pattern 2: "Test Helper"

This pattern creates individual tests, but puts a common test body in a helper method so it can be reused.

function testSomeMethod(foo, bar) {
    assert(subject(foo) == "bar");
}

it("puts the milk in the fridge", function () {
    testSomeMethod("milk", "fridge");
});

it("puts the cereal in the pantry", function () {
    testSomeMethod("cereal", "pantry");
});

Examples above are very simple, but either the test loop or the test helper pattern can be used to encapsulate a much more complicated series of steps (set up a request, look at some response headers / bodies, etc.).

Upvotes: 1

Related Questions