Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha -- before() doesn't execute 'before' as expected?

In a mocha+chai test code, I have a before block that initializes some variable "accPolicyData.accSizes".

  1 var expect = require('chai').expect;
  2 var dataDriven = require('data-driven');
  3 var accPolicyData = require("./samples/accounts-policy-data");
  4 var configReadr;
  5 var ecpDB;    // = require('ecp_model');
  6 var utils = require('../test_utils');
  7 
  8 describe("Test suite for account policy limits validation", function() {
  9 
 10   before(function(done) {  
 11 
 12     // read and process commandline args.
 13     var args = utils.processArgs(process.argv);
 14     console.log("Args:", args);
 15     global.args = args;    
 16     configReader = require('../config_reader')();
 17     configReader.read().then(function() {
 18       ecpDB = require('ecp_model');   
 19 
 20       // Read the policy limits from ecp db
 21       ecpDB.AccountTemplate.findAll().then(function(results) {
 22         return results.map(function(item) { return item.toJSON(); });
 23       }).then(function(results) {     
 24         accPolicyData.accSizes = results;
 25         return done();
 26       })
 27     });
 28   }); //EOF:before

Once the var is initialized (line#24), I plan to use the populated data in the subsequent describe block by looping through the resultset (line#39).

 36   describe("test cases", function() {
 37     // Iterate the account types array
 38     //dataDriven(accPolicyData.accTypes,function(type) {
 39     accPolicyData.accSizes.map(function(item) {
 40       console.log("Iterating through data...", item);
 41       testAccSizePolicy(type);
 42     });
 43     //});
 44   })

However, the problem is that this array doesn't get populated by the time this describe block gets executed, and hence the loop doesn't get executed. It executes correctly, if I directly have an "it()" block in the describe, but somehow fails for array iteration.

My before() code is asynchronous, and I have taken care to call the done() function correctly.

So, it appears that the code which is not part of it(...) will get executed early (before the done callback), and that code which is inside "it" executes in a sequential manner.

Is my understanding right?

I was trying to avoid code repetition of mutliple describe/it blocks, by way of using nested loops. Somehow it seems I cannot achieve this. Any ideas here?

like image 544
Mopparthy Ravindranath Avatar asked Sep 28 '16 06:09

Mopparthy Ravindranath


People also ask

What is before each in mocha?

Mocha has several hooks, including before, after, beforeEach, and afterEach. They make it possible to intercept tests before or after the test run and to perform specific tasks. For example, the beforeEach hook intercepts your test right before each test in a suite is run.


1 Answers

Mocha is designed in a way that requires it to know ahead of time all the tests that exist so all callbacks passed to describe are executed immediately, whereas all the hooks (before, beforeEach, etc.) and the tests (it) register their callbacks for future execution. Then, when Mocha is ready to actually run the tests, it calls these callbacks.

Ultimately, it looks like what you are trying to do is generate your test suite from an asynchronous algorithm. Mocha does not allow you to generate your test suite from the hooks, or from the tests. You cannot call it from inside a before call, etc. If you try, you can probably find situations where it appears to work as expected but as soon as you have a real suite (by opposition to a proof of concept), you'll run into bizarre behavior.

You can generate a test suite asynchronously by using --delay. (You probably should put it in mocha.opts so that it is always used.) And then you call run() once your suite is built. (Search for "delayed root suite" on this page.)

like image 80
Louis Avatar answered Sep 20 '22 22:09

Louis