Question

Essayer de se mettre au courant avec Node.js et NodeUnit, mais je trouve un problème avec NodeUnit où il ne voit pas l'appel à test.done() dans l'un des tests.

Le code:

// Added for clarity.
var client = require("restify").createJsonClient({
    "version": "*",
    "url": "http://localhost:" + server.Port
});

exports["tests"] = {
    "setUp": function (callback) {
        server.StartServer();
        callback();
    },
    "tearDown": function (callback) {
        callback();
    },
    "CanIHaveSomeTeaPlease?": function (test) {
        test.expect(4);
        client.get("/tea", function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    },

    // Note: I expect this test to fail as it is a copy of the above
    //       test on a different url that doesn't return the ImATeapot
    //       HTTP error. But it doesn't look like it's detecting it
    //       properly.

    "TakeThisInfo": function (test) {
        test.expect(4);
        client.put("/push", {
            "hello": "world"
        }, function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    }
};

Production:

FAILURES: Undone tests (or their setups/teardowns):
- tests - TakeThisInfo

To fix this, make sure all tests call test.done()

J'espère que c'est quelque chose de stupide.

Versions: -

Node: 0.10.21
NPM: 1.3.11
Nodeunit: 0.8.2
Grunt-CLI: 0.1.10
Grunt: 0.4.1
Était-ce utile?

La solution

Tout d'abord, je ne sais pas ce qu'est le "serveur" dans votre code, mais je m'attendrais à ce qu'il soit asynchrone, donc d'avoir quelque chose de plus comme ça dans votre fonction de configuration:

function (callback) {
  server.StartServer(function(){
    callback();
  });
}

Deuxièmement, restez à présent que Exécute le démarrage et les fonctions de démontage après et avant chaque test Je soupçonne donc que vous démarrez votre serveur 2 fois (comme dans le démontage, vous ne le fermez pas vraiment).

Autres conseils

J'ai passé les deux dernières heures à jouer avec ce problème, et ce qui est devenu clair, c'est que NodeUnit n'a pas la possibilité de capturer et d'afficher des exceptions lancées dans des fonctions qui sont déclenchées plus tard par un processus de type IO ou Settimeout. Compte tenu de la façon dont JavaScript fonctionne, ce n'est pas surprenant. Tout fonctionne une fois que vous êtes sûr qu'il n'y a pas d'exceptions, mais si vous avez une erreur dans votre code, vous recevrez un message "Tests annulé" et rien d'autre. Voici ce que j'ai fait pour résoudre mes problèmes (en utilisant un itinéraire Restify comme exemple):

function myRoute(req, res, next) {
    try {
        // your code goes here...
    }
    catch (err) {
        // write it to the console (for unit testing)
        console.log(err);
        // pass the error to the next function.
        next(err);
    }
}

Une fois que j'ai compris le problème de cette manière, le réparer parce que beaucoup plus clair et j'ai pu faire passer tous mes tests!

Je soupçonne que tu n'appelles pas vraiment test.done() Dans ce deuxième test. Mettre un console.log() Appelez là-dedans pour vérifier que vous passez cet appel.

FWIW, j'ai reproduit le problème décrit en utilisant une version simplifiée de votre test ci-dessous. Si vous omettez le on('error', function() {...}) Handler, puis le 2ème test ne parvient pas à se terminer. Ainsi, ma théorie est que votre /push Le point de terminaison déclenche un comportement différent dans le module Distify. C'est-à-dire que tu es Bien sur Restify invoque votre rappel avec un err propriété là-bas, ou fait-il quelque chose de différent? ... comme, par exemple, émettre un événement comme http.get fait, ci-dessous.

var http = require('http');

exports.test1 = function (test) {
  test.expect(1);
  http.get({hostname: "www.broofa.com", path: "/"}, function (res) {
    test.equal(res.statusCode, 200, 'got 200');
    test.done();
  });
};

exports.test2 = function (test) {
  test.expect(1);
  http.get({hostname: "www.no-such-domain.com", path: "/"}, function (res) {
    test.equal(res.statusCode, 200, 'got 200');
    test.done();
  }).on('error', function() {
    // Comment line below out to repro the "Undone tests" error
    test.done();
  });
};

Je travaille autour de lui en fournissant le serveur dans son propre processus dans la configuration, puis en le tuant dans le démontage. Pensez que le problème était de faire avec le serveur créé et non d'arrêter. Merci @matteofigus pour cela.

var cp = null; // child process
exports["tests"] = {
    "setUp": function (callback) {
        cp = fork("./lib/server.js", {"silent": true});
        callback();
    },
    "tearDown": function (callback) {
        cp.kill("SIGHUP");
        callback();
    },
    "CanIHaveSomeTeaPlease?": function (test) {
        test.expect(4);
        client.get("/tea", function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    },
    "TakeThisInfo": function (test) {
        test.expect(1);
        client.put("/push", {
            "hello": "world"
        }, function (err, req, res, data) {
            test.ok(false);
            test.done();
        });
    }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top