Je veux exécuter une petite base de données PostgreSQL qui ne fonctionne qu'en mémoire, pour chaque test unitaire que j'écris. Par exemple:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
Idéalement, je vais avoir un seul exécutable postgres vérifié dans le contrôle de version, que le test unitaire utilisera.
Quelque chose comme HSQL
, mais pour postgres. Comment puis je faire ça?
Où puis-je obtenir une telle version de Postgres? Comment puis-je lui dire de ne pas utiliser le disque?
testcontainers
, qui permet essentiellement à votre test de démarrer une instance jetable, dockerisée, postgres. Voir github.com/testcontainers/testcontainers-java/blob/master(Déplacer ma réponse de Utiliser PostgreSQL en mémoire et la généraliser):
Vous ne pouvez pas exécuter Pg en cours de traitement, en mémoire
Non ce n'est pas possible. PostgreSQL est implémenté en C et compilé en code de plateforme. Contrairement à H2 ou Derby, vous ne pouvez pas simplement charger le
jar
et le lancer comme une base de données en mémoire jetable.Contrairement à SQLite, qui est également écrit en C et compilé en code de plate-forme, PostgreSQL ne peut pas non plus être chargé en cours de traitement. Il nécessite plusieurs processus (un par connexion) car il s'agit d'une architecture multitraitement et non multithreading. L'exigence de multitraitement signifie que vous devez lancer le postmaster en tant que processus autonome.
Au lieu de cela: préconfigurer une connexion
Je suggère simplement d'écrire vos tests pour vous attendre à ce qu'un nom d'hôte / nom d'utilisateur / mot de passe particulier fonctionne, et que le test exploite
CREATE DATABASE
une base de données jetable, puisDROP DATABASE
à la fin de la course. Obtenez les détails de connexion à la base de données à partir d'un fichier de propriétés, des propriétés de la cible de construction, d'une variable d'environnement, etc.Vous pouvez utiliser en toute sécurité une instance PostgreSQL existante dans laquelle vous avez déjà des bases de données qui vous intéressent, tant que l'utilisateur que vous fournissez à vos tests unitaires n'est pas un super-utilisateur, seulement un utilisateur avec des
CREATEDB
droits. Au pire, vous créerez des problèmes de performances dans les autres bases de données. Je préfère exécuter une installation PostgreSQL complètement isolée pour tester pour cette raison.Au lieu de cela: lancez une instance PostgreSQL jetable à des fins de test
Alternativement, si vous êtes vraiment envie que vous pourriez avoir votre harnais de test localiser les
initdb
etpostgres
binaires, exécutezinitdb
pour créer une base de données, modifierpg_hba.conf
àtrust
, courirpostgres
pour le démarrer sur un port aléatoire, créez un utilisateur, créez un DB, et exécuter les tests . Vous pouvez même regrouper les binaires PostgreSQL pour plusieurs architectures dans un fichier jar et décompresser ceux de l'architecture actuelle dans un répertoire temporaire avant d'exécuter les tests.Personnellement, je pense que c'est une douleur majeure qui devrait être évitée; il est beaucoup plus facile de configurer simplement une base de données de test. Cependant, c'est devenu un peu plus facile avec l'avènement du
include_dir
support danspostgresql.conf
; maintenant, vous pouvez simplement ajouter une ligne, puis écrire un fichier de configuration généré pour tout le reste.Des tests plus rapides avec PostgreSQL
Pour plus d'informations sur la façon d' améliorer en toute sécurité les performances de PostgreSQL à des fins de test, consultez une réponse détaillée que j'ai écrite sur ce sujet plus tôt: Optimiser PostgreSQL pour des tests rapides
Le dialecte PostgreSQL de H2 n'est pas un véritable substitut
Certaines personnes utilisent à la place la base de données H2 en mode dialecte PostgreSQL pour exécuter des tests. Je pense que c'est presque aussi mauvais que les gens de Rails qui utilisent SQLite pour les tests et PostgreSQL pour le déploiement en production.
H2 prend en charge certaines extensions PostgreSQL et émule le dialecte PostgreSQL. Cependant, c'est juste cela - une émulation. Vous trouverez les zones où H2 accepte une requête mais PostgreSQL qui ne fonctionne pas, où diffère du comportement, etc . Vous trouverez également de nombreux endroits où PostgreSQL prend en charge ce que H2 ne peut tout simplement pas faire - comme les fonctions de fenêtre, au moment de l'écriture.
Si vous comprenez les limites de cette approche et que votre accès à la base de données est simple, H2 peut être OK. Mais dans ce cas, vous êtes probablement un meilleur candidat pour un ORM qui résume la base de données car vous n'utilisez de toute façon pas ses fonctionnalités intéressantes - et dans ce cas, vous n'avez plus à vous soucier de la compatibilité de la base de données.
Les tablespaces ne sont pas la solution!
N'utilisez pas d' espace de table pour créer une base de données «en mémoire». Non seulement cela n'est pas nécessaire car cela n'aidera pas de manière significative les performances de toute façon, mais c'est aussi un excellent moyen de perturber l'accès à tout autre élément qui pourrait vous intéresser dans la même installation PostgreSQL. La documentation 9.4 contient désormais l'avertissement suivant :
parce que j'ai remarqué que trop de gens faisaient cela et avaient des problèmes.
(Si vous avez fait cela, vous pouvez
mkdir
le répertoire de tablespace manquant pour redémarrer PostgreSQL, puisDROP
les bases de données manquantes, les tables, etc. Il vaut mieux ne pas le faire.)la source
initdb
installer une toute nouvelle Pg là-bas. Mais en réalité, il y a peu de différence entre un Pg qui a été modifié pour des tests rapides sur un stockage normal (fsync = off et d'autres fonctionnalités de durabilité / sécurité des données désactivées) que de s'exécuter sur un disque virtuel, du moins sous Linux.Ou vous pouvez créer un TABLESPACE dans un ramfs / tempfs et y créer tous vos objets.
On m'a récemment signalé un article sur le fait de faire exactement cela sous Linux .
avertissement
Cela peut mettre en danger l'intégrité de l' ensemble de votre cluster de base de données .
Lisez l'avertissement ajouté dans le manuel.
Ce n'est donc qu'une option pour les données non durables.
Pour les tests unitaires, cela devrait fonctionner correctement. Si vous exécutez d'autres bases de données sur la même machine, veillez à utiliser un cluster de base de données distinct (qui a son propre port) pour être sûr.
la source
initdb
une nouvelle instance de postgres dans un tempfs ou un ramdisk. N'utilisez pas de tablespace dans un tempfs etc, c'est fragile et inutile. Il vaut mieux utiliser un tablespace normal et créer desUNLOGGED
tables - il fonctionnera de la même manière. Et il ne traitera pas les performances WAL et les facteurs fsync à moins que vous ne preniez des mesures qui risquent de compromettre l'intégrité de l'ensemble de la base de données (voir stackoverflow.com/q/9407442/398670 ). Ne fais pas ça.Il est maintenant possible d'exécuter une instance en mémoire de PostgreSQL dans vos tests JUnit via le composant PostgreSQL intégré d'OpenTable: https://github.com/opentable/otj-pg-embedded .
En ajoutant la dépendance à la bibliothèque intégrée otj-pg ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ), vous pouvez démarrer et arrêter votre propre instance de PostgreSQL dans votre @Before et @Afer crochets:
Ils proposent même une règle JUnit pour que JUnit démarre et arrête automatiquement votre serveur de base de données PostgreSQL pour vous:
la source
@Rule
avec@ExtendWith
? Utilisez simplement le.start()
in@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Vous pouvez utiliser TestContainers pour lancer un conteneur Docker PosgreSQL pour les tests: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers fournit un JUnit @ Rule / @ ClassRule : ce mode démarre une base de données dans un conteneur avant vos tests et la déchire ensuite.
Exemple:
la source
Il existe maintenant une version en mémoire de PostgreSQL de la société de recherche russe nommée Yandex: https://github.com/yandex-qatools/postgresql-embedded
Il est basé sur le processus d'intégration de Flapdoodle OSS.
Exemple d'utilisation (à partir de la page github):
Je l'utilise depuis un certain temps. Ça marche bien.
MISE À JOUR : ce projet n'est plus activement maintenu
la source
Vous pouvez également utiliser les paramètres de configuration PostgreSQL (tels que ceux détaillés dans la question et la réponse acceptée ici ) pour obtenir des performances sans nécessairement recourir à une base de données en mémoire.
la source
Si vous utilisez NodeJS, vous pouvez utiliser pg-mem (avertissement: je suis l'auteur) pour émuler les fonctionnalités les plus courantes d'une base de données postgres.
Vous disposerez d'une base de données en mémoire complète, isolée et indépendante de la plate-forme, répliquant le comportement PG (elle fonctionne même dans les navigateurs ).
J'ai écrit un article pour montrer comment l'utiliser pour vos tests unitaires ici .
la source