web-dev-qa-db-fra.com

Base de données moqueuse dans node.js?

Comment puis-je simuler la base de données dans mon application node.js, qui dans ce cas utilise mongodb comme backend pour un blog REST API?

Bien sûr, je pourrais définir la base de données sur une base de données testing spécifique, mais je continuerais à enregistrer des données et à ne pas tester mon code uniquement, mais également la base de données, donc je ne fais pas de tests unitaires mais des tests d'intégration.
Alors que faire? Créer des wrappers de base de données en tant que couche intermédiaire entre l'application et la base de données et remplacer le DAL lors des tests?

// app.js  
var express = require('express');
    app = express(),
    mongo = require('mongoskin'),
    db = mongo.db('localhost:27017/test?auto_reconnect');

app.get('/posts/:slug', function(req, res){
    db.collection('posts').findOne({slug: req.params.slug}, function (err, post) {
        res.send(JSON.stringify(post), 200);
    });
});

app.listen(3000);

// test.js
r = require('requestah')(3000);
describe("Does some testing", function() {

  it("Fetches a blogpost by slug", function(done) {
    r.get("/posts/aslug", function(res) {
      expect(res.statusCode).to.equal(200);
      expect(JSON.parse(res.body)["title"]).to.not.equal(null);
      return done();
    });

  });
));
68
Industrial

Je ne pense pas que le code lié à la base de données puisse être correctement testé sans le tester avec le logiciel de base de données. C'est parce que le code que vous testez n'est pas seulement javascript mais aussi la chaîne de requête de la base de données. Même si, dans votre cas, les requêtes semblent simples, vous ne pouvez pas compter sur cela de cette façon pour toujours.

Ainsi, toute couche d'émulation de base de données implémentera nécessairement la totalité de la base de données (moins le stockage sur disque peut-être). D'ici là, vous finissez par faire des tests d'intégration avec l'émulateur de base de données même si vous l'appelez tests unitaires. Un autre inconvénient est que l'émulateur de base de données peut finir par avoir un ensemble différent de bogues par rapport à la base de données et vous pouvez finir par devoir coder à la fois pour l'émulateur de base de données et la base de données (un peu comme la situation avec IE vs Firefox vs Chrome etc.).

Par conséquent, à mon avis, la seule façon de tester correctement votre code est de l'interfacer avec la vraie base de données.

109
slebetman

Il existe une règle générale en matière de moquerie qui est

Ne vous moquez pas de tout ce que vous ne possédez pas.

Si vous souhaitez simuler la base de données, cachez-la derrière une couche de service abstraite et simulez cette couche. Assurez-vous ensuite que vous testez l'intégration de la couche de service réelle.

Personnellement, j'ai cessé d'utiliser des simulateurs pour les tests et de les utiliser pour une conception de haut en bas, ce qui m'aide à conduire le développement du haut vers le bas en mockant les couches de service au fur et à mesure, puis en mettant finalement en œuvre ces couches et en écrivant des tests d'intégration. Utilisés comme outil de test, ils ont tendance à rendre votre test très fragile et, dans le pire des cas, à conduire à une divergence entre le comportement réel et le comportement moqué.

40
christkv

Je ne suis pas d'accord avec la réponse sélectionnée ou d'autres réponses jusqu'à présent.

Ne serait-ce pas génial si vous pouviez détecter les erreurs engendrées par les changements chaotiques et souvent désordonnés apportés aux schémas DB et à votre code AVANT qu'il n'atteigne l'AQ? Je parie que la majorité crierait diable oui!

Vous pouvez et devez très certainement isoler et tester vos schémas de base de données. Et vous ne le faites pas sur la base d'un émulateur ou d'une image lourde ou d'une recréation de votre base de données et de votre machine. C'est ce que des choses comme SQLite sont à titre d'exemple. Vous la moquez en vous basant sur une instance légère en mémoire en cours d'exécution et avec des données statiques qui ne changent pas dans cette instance en mémoire, ce qui signifie que vous testez réellement votre base de données de manière isolée et que vous pouvez également faire confiance à vos tests. Et évidemment, c'est rapide car il est en mémoire, un squelette, et est mis au rebut à la fin d'un test.

Alors oui, vous devriez et vous devriez tester le SCHEMA qui est exporté dans une instance de mémoire très légère de tout moteur DB/runtime que vous utilisez, et qui, avec l'ajout d'une très petite quantité de données statiques, devient votre base de données factice isolée.

Vous exportez vos vrais schémas de votre vraie base de données périodiquement (de manière automatisée) et vous les importez/mettez à jour dans votre instance de base de données légère en mémoire avant chaque Push to QA et vous saurez instantanément si les dernières modifications apportées à la base de données par vos administrateurs de base de données ou autres les développeurs qui ont récemment modifié le schéma ont réussi tous les tests.

Bien que j'applaudisse l'effort de faire de votre mieux pour répondre, je voterais contre la réponse actuelle si je le pouvais, mais je suis nouveau et je n'ai pas encore acquis suffisamment de réputation pour pouvoir encore le faire.

Quant à la personne qui a répondu "ne vous moquez pas de tout ce qui ne vous appartient pas". Je pense qu'il voulait dire "ne testez rien de ce que vous ne possédez pas". Mais vous vous moquez de choses que vous ne possédez pas! Parce que ce sont des choses non testées qui doivent être isolées!

J'ai l'intention de partager le COMMENT avec vous et je mettrai à jour ce message dans un futur proche avec un exemple réel de code JS!

C'est ce que font de nombreuses équipes de test. Il suffit de comprendre le comment.

36
PositiveGuy

Mon approche préférée pour tester le code DB d'unité dans n'importe quelle langue est d'accéder à Mongo via une abstraction du référentiel (il y a un exemple ici http://iainjmitchell.com/blog/?p=884 ). Les implémentations varieront en termes de fonctionnalités spécifiques aux bases de données exposées, mais en supprimant tout le code Mongo de votre propre logique, vous êtes en mesure d'effectuer un test unitaire. Remplacez simplement l'implémentation de Mongo Repository par une version tronquée qui est très simple. Par exemple, il suffit de stocker des objets dans une simple collection de dictionnaires en mémoire.

Vous bénéficierez des avantages d'un test unitaire de votre propre code de cette manière sans dépendances de base de données, mais vous devrez toujours effectuer des tests d'intégration par rapport à la base de données principale, car vous ne pourrez probablement jamais émuler les idiosyncrasies de la vraie base de données comme d'autres l'ont fait. dit ici. Le genre de choses que j'ai trouvées sont aussi simples que l'indexation en mode sans échec vs sans mode sans échec. Plus précisément, si vous avez un index unique, votre implémentation de mémoire factice pourrait honorer cela dans tous les cas, mais Mongo ne le fera pas sans mode sans échec.

Ainsi, même si vous devrez toujours tester la base de données pour certaines opérations, vous pourrez certainement tester correctement votre propre logique avec une implémentation de référentiel tronquée.

4
cirrus

Le but de la moquerie est de sauter le code propre de la complexité et du test unitaire. Si vous souhaitez écrire des tests e2e, utilisez la base de données.

Écrire du code pour configurer/démonter une base de données de test pour les tests unitaires est une dette technique et incroyablement insatisfaisante.

Il existe de fausses bibliothèques dans npm:

mongo - https://www.npmjs.com/package/mongomock

mangouste - https://www.npmjs.com/package/mockgoose

Si ceux-ci ne prennent pas en charge les fonctionnalités dont vous avez besoin, alors oui, vous devrez peut-être utiliser la vraie chose.

4
Michael Cole

J'ai eu ce dilemme et j'ai choisi de travailler avec une base de données de test et de la nettoyer à chaque fois que le test commence. (comment tout supprimer: https://stackoverflow.com/a/25639377/378594 )

Avec NPM, vous pouvez même créer un script de test qui crée le fichier db et le nettoie ensuite.

2
Uri