Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha test case - are nested it( ) functions kosher?

I have this case where I think I want to have nested it() test cases in a Mocha test. I am sure this is wrong, and I don't see any recommendations to do what I am doing, but I don't really know of a better way at the moment -

basically, I have a "parent" test, and inside the parent test there's a forEach loop with all the "child" tests:

it('[test] enrichment', function (done) {

        var self = this;

        async.each(self.tests, function (json, cb) {

            //it('[test] ' + path.basename(json), function (done) {

                var jsonDataForEnrichment = require(json);
                jsonDataForEnrichment.customer.accountnum = "8497404620452729";
                jsonDataForEnrichment.customer.data.accountnum = "8497404620452729";
                var options = {
                    url: self.serverURL + ':' + self.serverPort + '/event',
                    json: true,
                    body: jsonDataForEnrichment,
                    method: 'POST'
                };


               request(options,function (err, response, body) {
                    if (err) {
                        return cb(err);
                    }

                     assert.equal(response.statusCode, 201, "Error: Response Code");
                     cb(null);


                });

            //});

        }, function complete(err) {
            done(err)
        });

    });

as you can see, two separate lines are commented out - I want to include them so that I can easily see the results of each separate test, but then I have this awkward situation of firing the callback for the test alongside the callback for async.each.

Has anyone seen this time of situation before and know of a good solution where the tester can easily see the results of each test in a loop?

like image 272
Alexander Mills Avatar asked Sep 23 '15 20:09

Alexander Mills


2 Answers

Don't nest it calls. Call them synchronously.

Nested it calls are never okay in Mocha. Nor are it calls performed asynchronously. (The test can be asynchronous, but you cannot call it asynchronously.) Here's a simple test:

describe("level 1", function () {
    describe("first level 2", function () {
        it("foo", function () {
            console.log("foo");
            it("bar", function () {
                console.log("bar");
            });
        });

        setTimeout(function () {
            it("created async", function () {
                console.log("the asyncly created one");
            });
        }, 500);
    });

    describe("second level 2", function () {
        // Give time to the setTimeout above to trigger.
        it("delayed", function (done) {
            setTimeout(done, 1000);
        });
    });
});

If you run this you won't get the nested test bar will be ignored and the test created asynchronously (delayed) will also be ignored.

Mocha has no defined semantics for these kinds of calls. When I ran my test with the latest version of Mocha at the time of writing (2.3.3), it just ignored them. I recall that an earlier version of Mocha would have recognized the tests but would have attached them to the wrong describe block.

like image 130
Louis Avatar answered Oct 06 '22 19:10

Louis


I think the need for dynamic tests are relatively common (data-driven tests?), and there is common use for dynamic it and test cases.

I think it could be easier to manage testcase completion if tests could be executed in series. This way you wouldn't have to worry about managing nested async done's. Since request is async (i'm assuming), your test cases will still mainly be executing concurrently.

describe('[test] enrichment', function () {

        var self = this;


        _.each(self.tests, function (json, cb) {

            it('[test] ' + path.basename(json), function (done) {

                var jsonDataForEnrichment = require(json);
                jsonDataForEnrichment.customer.accountnum = "8497404620452729";
                jsonDataForEnrichment.customer.data.accountnum = "8497404620452729";
                var options = {
                    url: self.serverURL + ':' + self.serverPort + '/event',
                    json: true,
                    body: jsonDataForEnrichment,
                    method: 'POST'
                };


               request(options,function (error, response, body) {
                    if (error) {
                        cb(error);

                    }
                    else{
                        assert.equal(response.statusCode, 201, "Error: Response Code");
                        cb(null);
                    }

                    done(); 
                });

            });

        }
    });
like image 33
dm03514 Avatar answered Oct 06 '22 19:10

dm03514