Mon application comporte plusieurs couches: middleware, contrôleurs, gestionnaires. L'interface des contrôleurs est identique à celle des middlewares: (req, res, next).
Ma question est donc: comment puis-je tester mes contrôleurs sans démarrer le serveur et envoyer de "vraies" demandes à localhost. Ce que je veux faire est de créer une requête, des instances de réponse comme le fait nodejs, puis d'appeler simplement la méthode des contrôleurs.
Quelque chose comme ça:
var req = new Request()
var res = new Response()
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
Tout conseil est fortement apprécié. Merci!
P.S. la raison pour laquelle je veux le faire est qu'à la fin je voudrais tester si l'objet de réponse contient des variables correctes pour les vues jade.
Exiger:
var mocks = require('node-mocks-http');
vous pouvez ensuite composer des objets req et response:
req = mocks.createRequest();
res = mocks.createResponse();
Vous pouvez ensuite tester directement votre contrôleur:
var demoController = require('demoController');
demoController.login(req, res);
assert.equal(res.json, {})
mise en garde
Il existe au moment de la rédaction d'un problème dans cette implémentation lié au fait que l'émetteur d'événement n'est pas déclenché.
Étant donné que JavaScript est un langage typé dynamiquement, vous pouvez créer des objets fictifs et les transmettre à vos contrôleurs comme suit:
var req = {};
var res = {};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
Si votre contrôleur a besoin d'une donnée ou d'une fonctionnalité particulière de votre objet de demande ou de réponse, vous devrez fournir ces données ou fonctionnalités dans vos simulations. Par exemple,
var req = {};
req.url = "http://google.com"; // fake the Url
var res = {};
res.write = function(chunk, encoding) {
// fake the write method
};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
J'essaierais d'utiliser dupertest pour cela. C'est un module de nœud que j'ai créé dans le but même de tester facilement le contrôleur sans avoir à faire tourner un nouveau serveur.
Il conserve la syntaxe familière des modules de nœuds comme request
ou supertest
, mais encore une fois, sans avoir besoin de faire tourner un serveur.
Il fonctionne un peu comme Hector l'a suggéré ci-dessus, mais s'intègre à un cadre de test comme Jasmine pour se sentir un peu plus transparent.
Un exemple relatif à votre question peut ressembler à:
request(controller.get_user)
.params({id: user_id})
.expect(user, done);
Ou la version longue plus explicite:
request(controller.get_user)
.params({id: user_id})
.end(function(response) {
expect(response).toEqual(user);
done();
});
Remarque: les exemples supposent user_id
et user
sont définis quelque part, et que le contrôleur récupère et renvoie un utilisateur en fonction de l'id.
Edit: en lisant votre réponse à une réponse ci-dessus, je reconnais que l'inconvénient est que ce module n'intègre pas par défaut une requête factice ou un objet de réponse plus robuste. dupertest
facilite l'extension et l'ajout de propriétés aux deux req
et res
, mais par défaut, elles sont assez nues.
Un post un peu ancien, mais je voudrais donner mes 2 cents. L'approche que vous souhaitez adopter varie selon que vous effectuez des tests unitaires ou des tests d'intégration. Si vous suivez la voie de l'utilisation de supertest, cela signifie que vous exécutez le code d'implémentation réel et que vous effectuez des tests d'intégration. Si c'est ce que vous voulez faire, cette approche est très bien.
Mais si vous faites des tests unitaires, vous vous moquerez des objets req et res (et de toute autre dépendance impliquée). Dans le code ci-dessous (code non pertinent supprimé par souci de concision), je me moque de res et ne donne qu'une implémentation simulée de la méthode json, car c'est la seule méthode dont j'ai besoin pour mes tests.
// SUT
kids.index = function (req, res) {
if (!req.user || !req.user._id) {
res.json({
err: "Invalid request."
});
} else {
// non-relevent code
}
};
// Unit test
var req, res, err, sentData;
describe('index', function () {
beforeEach(function () {
res = {
json: function (resp) {
err = resp.err;
sentData = resp.kids;
}
};
});
it("should return error if no user passed in request", function () {
req = {};
kidsController.index(req, res);
expect(err).to.equal("Invalid request.");
});
/// More tests....
})
Si vous souhaitez utiliser les vrais objets req
et res
, vous devez envoyer de vraies requêtes au serveur. Cependant, c'est beaucoup plus facile que vous ne le pensez. Il y a beaucoup d'exemples à l'express github repo . Ce qui suit montre les tests pour req.route
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.route', function(){
it('should be the executed Route', function(done){
var app = express();
app.get('/user/:id/edit', function(req, res){
// test your controllers with req,res here (like below)
req.route.method.should.equal('get');
req.route.path.should.equal('/user/:id/edit');
res.end();
});
request(app)
.get('/user/12/edit')
.expect(200, done);
})
})
})