javascriptnode.jsmocha.jsshould.js

Node.js & Mocha/Should (JavaScript, ES6): Code not executed although it looks like it should


I trying to write some test code in a nodejs project using mocha/should and request.

My code initializes an array with some web addresses in order to send a GET request to a remote server and check the content of the responses.

My mock-up right now just needs to print out the response however for some reason the flow never gets there.

Note that I have a for loop. Inside the loop the first console log prints stuff out, however for some reason the rest of the code inside that loop is being skipped. I put break points in debug mode but my code only reaches the first console.log() inside the loop and the request part is skipped.

I tried to use also the unpromisified version of request (streams and all) but I get the same problem - the code never reached that request line so of course it doesn't go any further to printing anything inside.

Is it something to do with asynchronous work inside nodejs? something else?

What am I missing?

'use strict';
const Promise = require('bluebird')
	, _ = require('underscore')
	, should = require('should')
	, r = require('request')
	, request = Promise.promisifyAll(r.defaults({jar: true}))
	, client = require('../whatever/someClient')
	, testConfig = require('../config/test-config')
;

Promise.longStackTraces();

class someFeatureTestSet {
	
	constructor() {
		//...
		this.client = client.getUser();
		//...
	}
	
	static create() { return new someFeatureTestSet(); }
	
//... some other consts and functions
	
	initURLs(someUrlParamVal) {
		return Array
		.apply(null, Array(someUrlParamVal))
		.map((x, idx) =>
			`http://example.com/whatever?c=${someUrlParamVal}`
		);
	}
	
	runTests() {
		const client = this.client;
		const someFeatureTestSet = this;
		
		describe('get stuff', () => {
			
			it('should bla', () => {
				const productsLinks = this.initURLs('123');

				for (let x in productsLinks) {
					console.log(productsLinks[x]); //gets printed, no problem
					request.getAsync({ uri: productsLinks[x] }) 
					.then(res => { //code never gets here. why?
						console.log(res); //code never gets here. why?
					})
				}

			});
			
		} );
		
	}
	
}

module.exports = someFeatureTestSet;

const createTestSet = () => someFeatureTestSet.create();

createTestSet().client().runTests();


Solution

  • You need to either return a Promise or call the done() callback after running async tests. Since you are running async requests in a loop you need to accumulate the request promises in an array and use Promise.all()

    it('should bla', () => {
      const productsLinks = this.initURLs('123');
      let requests = [];
    
      for (let x in productsLinks) {
        console.log(productsLinks[x]); //gets printed, no problem
        requests.push(request.getAsync({ uri: productsLinks[x] }));
      }
    
      return Promise.all(requests);
    });
    

    If you want to use done() you can do the following -

    it('should bla', (done) => {
      const productsLinks = this.initURLs('123');
      let requests = [];
    
      for (let x in productsLinks) {
        console.log(productsLinks[x]); //gets printed, no problem
        requests.push(request.getAsync({ uri: productsLinks[x] }));
      }
    
      Promise
        .all(requests)
        .then(() => {
          done();
        })
    });
    

    Note that, calling done() will fail if it exceeds the timeout set for running mocha tests. See here to learn more - https://mochajs.org/#timeouts