mocha中的多个before()或beforEach()

Gir*_*pta 2 bdd mocha.js node.js supertest

我需要在mocha中的before()钩子中做多个异步调用.我需要删除用户,然后注册,验证电子邮件,最后登录以获取令牌以验证所有其他测试用例.这是我的代码片段:

    const userInfo = {
        "password": "pass123",
        "email": "test@email.com",
    };

    var token = '' , userId = '';

    before((done) => {
        // Delete the  user if already exists
        User.remove({
                email: userInfo.email
            }).then((res) => {
              //  console.log(res.result);
            })
            .end(done);
        done();
    });


    before((done) => {
        request(app)
            .post('/api/users')        
            .send(userInfo)
            .expect(200)
            .expect((res) => {        
            })
            .end(done);
    });

    before((done) => {
        User.findOne({
                email: userInfo.email
            }).then((res) => {            
                userId = res._id;
                request(app)
                    .post('/api/users/verify-email')
                    .send({'token' : userId})
                    .expect(200)
                    .expect((res) => {                
                    })
                    .end(done);
            })
            .end(done);
        done();
    });
Run Code Online (Sandbox Code Playgroud)

这些调用不是按顺序执行的.我需要在验证电子邮件之前获取userId,但我收到以下错误:

POST /api/users/verify-email 401 4.082 ms - 45
    1) "before all" hook
Run Code Online (Sandbox Code Playgroud)

Ant*_*ich 9

首先,是的,mocha允许多个挂钩,并保证以正确的顺序调用它们.要确保这一点,您可以运行此代码段.

'use strict';

const results = [];
const assert = require('assert');

before(done => {
    setTimeout(() => {
        console.log(`First 'before'`);
        results.push(1);
        done(); //Will be called last
    }, 1000)
});

before(done => {
    setTimeout(() => {
        console.log(`Second 'before'`);
        results.push(2); //Will be called second
        done();
    }, 300)
});

before(done => {
    setTimeout(() => {
        console.log(`Third 'before'`);
        results.push(3); //Will be called first
        done();
    }, 100)
});

describe('Before hooks order', () => {
    it('should before hooks sequentially', () => {
        //Check if the hooks were called in the right order anyway
        assert.deepEqual(results, [1, 2, 3]);
    });
});
//Output is:
// First 'before'
// Second 'before'
// Third 'before'
Run Code Online (Sandbox Code Playgroud)

但为了实现这一点,只有在完成所有异步操作以让mocha知道钩子已完成且它应该运行下一个时,才需要调用done().

还有一个规则是任何Node.js回调只能被调用一次.所以这里有几个修复:

before((done) => {
    // Delete the  user if already exists
    User
        .remove({
            email: userInfo.email
        })
        .then((res) => {
            //  console.log(res.result);
        })
        .end(done);
    //Do not call done here() because User.remove have only started
    //We need to wait until it finishes. Done will be called in .end method
    // done();
});

before((done) => {
    //All good here
    request(app)
        .post('/api/users')
        .send(userInfo)
        .expect(200)
        .expect((res) => {
        })
        .end(done);
});

before((done) => {
    User.findOne({
        email: userInfo.email
    }).then((res) => {
        userId = res._id;
        //You need a return statement here so the outer promise waits
        //Until the internal call finishes
        return request(app)
            .post('/api/users/verify-email')
            .send({'token': userId})
            .expect(200)
            .expect((res) => {
            });
    //We must not call callback multiple times, so remove this.
    // .end(done);
    })
    //Now this 'end' will happen only after both calls finish
    .end(done);

    //Remove this please, for the same reason as with the first 'before'
    // done();
});
Run Code Online (Sandbox Code Playgroud)

请检查一下.我无法运行你的代码(没有你的api),所以请告诉我任何问题.