Home > Blockchain >  How to make Mocha unit test wait for async variable
How to make Mocha unit test wait for async variable

Time:03-27

I am very new to unit testing and I am trying to write a unit test on a function that reads from my database, but because the read is asynchronous the value is always undefined in my Mocha unit test. How can I do an assert on a variable which is declared asynchronously?

Unit Test:

const homeController = require('../controllers/homeController');

describe('Testing home_get function', function () {
  it ('should render the home page', function () {
    const req = {};
    homeController.home_get(req, null, () =>  {});
    console.log("numberUsers", numberUsers);
    assert.ok(numberUsers > 0);
  });
});

Function I am trying to test:

module.exports.home_get = async (req, res) => {
    requestTime = Date.now();
    numberUsers = await User.countDocuments({});
    numberViewers = await Viewer.countDocuments({});
    numberAccreditors = await Accreditor.countDocuments({});
    
    res.status('200').render('home', {numberUsers: numberUsers, numberViewers: numberViewers, numberAccreditors: numberAccreditors});
};

When I do an assert statement on the requestTime variable it works as intended but when I do it on the async variables the value is always undefined and I am not sure how to get the unit test to work on these async variables, also.... how would you then do a unit test to check the res.status is correct when you render home?

CodePudding user response:

You have two way to do that.

You can await your function in the test:

  it ('should render the home page', async function () {
    const req = {};
    await homeController.home_get(req, null, () =>  {});
    console.log("numberUsers", numberUsers);
    assert.ok(numberUsers > 0);
  });

or use the test callback function:

  it ('should render the home page', function (done) {
    const req = {};
    homeController.home_get(req, null, () =>  {}).then(() => {
      console.log("numberUsers", numberUsers);
      assert.ok(numberUsers > 0);
      done();
    });
  });

But in either case your function should return a value on which you can make the assert. There, the numberUsers is never declared and will still be undefined.

edit: Except if registered in the globals object because not using let, const or var. This is something you probably do not want to do.

CodePudding user response:

the main goal in unit testing is to only test 1 layer of logic, such as the function itself you have presented. every other thing must be a mock, otherwise it is an integration test that you require and not a unit test.

in this case, you are trying to actually run a query on a database, but it is not actually up and working, so what you get is undefined.

i suggest the following:

  1. if you want to actually query the database, run an integration test instead where it will actually work. integration tests are loading the whole application to test the interaction between all of the components.
  2. to complete the unit test itself, you should mock the database such as it returns what you expect it to return, so only those 5 lines in the function is actually running.
  • Related