oderfla
oderfla

Reputation: 1797

How to wait or share data between files in mocha

So lets say I have a file named "main.js". It contains this:

const User = require('../models/user');

describe('Testing', () => {
    before(async function(){
        await User.deleteMany({});
    });
    require('./users/createUser');
    require('./users/activateUser');
});

As you can see, before all tests, I clean the collection "users". Then I require 2 files. Their content is the following:

    //createUser.js

    let activationCode = undefined;

    describe('Create User', () => {
        it('it should POST a user when post data is valid', (done) => {
            chai.request(server)
                .post('/user/post')
                .send(userJson)
                .end((err, res) => {
                    res.should.have.status(200);
                    res.body.should.be.a('object');
                    res.body.should.have.property('message').eql('USER_ADDED');
                    activationCode = res.body.user.activationString;
                    done();
                });
        });

    });

    //activateUser.js

    //Here, Im in stuck because I dont have access to the variable activationCode created in createUser.js

As you can see, in the second required file, I would like to access the activationString created in the first required file. But it seems that the required files run in parallell, which makes it impossible to reach the variable from the other file.

What can I do? createUser.js should maybe be async som in main.js I wait it to be completed before requiring the second file?

Upvotes: 0

Views: 561

Answers (1)

Lin Du
Lin Du

Reputation: 102347

Mocha runs the test suite in serial mode by default, regardless of whether the code being tested is synchronous or asynchronous. Therefore, the test suite will be executed in the order in which the files are loaded by require.

You could be clever and try to get around this restriction by assigning something to the global object, but this will not work in parallel mode. It’s probably best to play by the rules!

This means you can declare activationCode variable as the property of the global object and access it across the test files in one process(serial mode). Different processes are allocated different memory, so global objects cannot be accessed across processes. which means this way will NOT work in parallel mode

Here is an example to show how to access activationCode variable via global object.

createUser.js:

global.activationCode = undefined;

describe('Create User', () => {
  it('should create user and get the activation code', (done) => {
    // simulate asynchronous operation
    setTimeout(() => {
      global.activationCode = 'success';
      console.log(new Date().toISOString());
      done();
    }, 3000);
  });
});

activateUser.js:

const { expect } = require('chai');

describe('Activate User', () => {
  it('should activate user', (done) => {
    setTimeout(() => {
      expect(global.activationCode).to.be.eql('success');
      console.log(new Date().toISOString());
      done();
    }, 1000);
  });
});

index.test.js:

describe('Testing', () => {
  before(function(done) {
    setTimeout(() => {
      console.log('delete user');
      console.log(new Date().toISOString());
      done();
    }, 1000);
  });
  require('./createUser');
  require('./activateUser');
});

test result:

  Testing
delete user
2020-12-23T12:10:00.585Z
    Create User
2020-12-23T12:10:03.587Z
      ✓ should create user and get the activation code (3000ms)
    Activate User
2020-12-23T12:10:04.590Z
      ✓ should activate user (1002ms)


  2 passing (5s)

Upvotes: 1

Related Questions