asedsami
asedsami

Reputation: 679

How not to repeat myself with duplicate tests in mocha

here's my test.js file, I'm trying to put some tests in the duplicateTests function and use this function in different test files:

function duplicateTests(user) {
    it('nested test 2', done => {
        console.log('user in duplicateTests function: ', user)

        if (user) {
            done()
        } else {
            done(new Error('Dummy error'))
        }
    })
}

describe('users', () => {
    let user

    before(async () => {
        user = await models.User.create({
            name: 'john',
        })
    })

    describe('TEST THE BEFORE HOOK', () => {
        it('test 1', done => {
            console.log('user: ', user)

            if(user) {
                done()
            } else {
                done(new Error('Dummy error'))
            }
        })

        duplicateTests(user)
    })
})

the log inside 'test 1' logs the user correctly:
user: { name: 'john' }

but the log inside 'nested test 2' logs this:
user in duplicateTests function: undefiend

so user is undefined in the nested test and the nested test fails as you could predict.

I tried returning a promise inside my 'before' hook but that didn't solve the problem.
Thanks for any help you are able to provide.

Upvotes: 1

Views: 265

Answers (1)

Marco
Marco

Reputation: 7261

This happens because duplicateTests() runs before before() has finished.

describe('users', async () => {
    let user

    user = await models.User.create({
        name: 'john',
    })

    describe('TEST THE BEFORE HOOK', () => {
        it('test 1', done => {
            console.log('user: ', user)

            if(user) {
                done()
            } else {
                done(new Error('Dummy error'))
            }
        })

        duplicateTests(user)
    })
})

Or you can exploit javascript's object reference:

function duplicateTests(context) {
    // let user = context.user doesnt work here
    // because before() has not run yet.

    it('nested test 2', done => {
        // reference is collapsed
        // we can be sure before() was called because
        // it is ran before any tests run
        let user = context.user

        console.log('user in duplicateTests function: ', user)

        if (user) {
            done()
        } else {
            done(new Error('Dummy error'))
        }
    })
}

describe('users', () => {
    let context = {}

    before(() => new Promise(async (resolve, reject) => {
        try {
            context.user = await models.User.create({
                name: 'john',
            })
            resolve()
        } catch (err) {
            reject(err)
        }
    }))

    describe('TEST THE BEFORE HOOK', () => {
        it('test 1', done => {
            console.log('user: ', context.user)

            if(context.user) {
                done()
            } else {
                done(new Error('Dummy error'))
            }
        })

        // context is passed by reference
        duplicateTests(context)
    })
})

Upvotes: 2

Related Questions