Quiero ejecutar una pequeña base de datos PostgreSQL que se ejecute solo en la memoria, para cada prueba unitaria que escribo. Por ejemplo:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
Idealmente, tendré un solo ejecutable de postgres registrado en el control de versiones, que usará la prueba unitaria.
Algo así HSQL
, pero para postgres. ¿Cómo puedo hacer eso?
¿Puedo obtener una versión de Postgres? ¿Cómo puedo indicarle que no utilice el disco?
testcontainers
, que esencialmente permite que su inicio de prueba sea una instancia de postgres desechable y dockerizada. Ver github.com/testcontainers/testcontainers-java/blob/master/…(Moviendo mi respuesta de Usar PostgreSQL en memoria y generalizándola):
No puede ejecutar Pg en proceso, en memoria
No, no es posible. PostgreSQL se implementa en C y se compila en el código de la plataforma. A diferencia de H2 o Derby, no puede simplemente cargar el
jar
y activarlo como una base de datos en memoria desechable.A diferencia de SQLite, que también está escrito en C y compilado en el código de la plataforma, PostgreSQL tampoco se puede cargar en el proceso. Requiere múltiples procesos (uno por conexión) porque es una arquitectura de multiprocesamiento, no de múltiples subprocesos. El requisito de multiprocesamiento significa que debe iniciar el administrador de correos como un proceso independiente.
En su lugar: preconfigura una conexión
Sugiero simplemente escribir sus pruebas para esperar que funcione un nombre de host / nombre de usuario / contraseña en particular, y hacer que la prueba aproveche
CREATE DATABASE
una base de datos desechable, luegoDROP DATABASE
al final de la ejecución. Obtenga los detalles de conexión de la base de datos de un archivo de propiedades, cree propiedades de destino, variable de entorno, etc.Es seguro usar una instancia de PostgreSQL existente en la que ya tiene bases de datos que le interesan, siempre que el usuario que proporcione a sus pruebas unitarias no sea un superusuario, solo un usuario con
CREATEDB
derechos. En el peor de los casos, creará problemas de rendimiento en las otras bases de datos. Prefiero ejecutar una instalación de PostgreSQL completamente aislada para realizar pruebas por ese motivo.En su lugar: inicie una instancia de PostgreSQL desechable para realizar pruebas
Alternativamente, si usted está realmente Keen usted podría tener su instrumento de prueba localizar las
initdb
ypostgres
los binarios, dirigidoinitdb
a crear una base de datos, modificarpg_hba.conf
atrust
, correrpostgres
para iniciarlo en un puerto aleatorio, crear un usuario, crear una base de datos, y ejecutar las pruebas . Incluso podría agrupar los binarios de PostgreSQL para múltiples arquitecturas en un contenedor y descomprimir los de la arquitectura actual en un directorio temporal antes de ejecutar las pruebas.Personalmente, creo que es un gran dolor que debe evitarse; es mucho más fácil configurar una base de datos de prueba. Sin embargo, se ha vuelto un poco más fácil con la llegada del
include_dir
soportepostgresql.conf
; ahora puede agregar una línea y luego escribir un archivo de configuración generado para el resto.Pruebas más rápidas con PostgreSQL
Para obtener más información sobre cómo mejorar de forma segura el rendimiento de PostgreSQL con fines de prueba, consulte una respuesta detallada que escribí sobre este tema anteriormente: Optimizar PostgreSQL para pruebas rápidas
El dialecto PostgreSQL de H2 no es un verdadero sustituto
En cambio, algunas personas usan la base de datos H2 en el modo de dialecto de PostgreSQL para ejecutar pruebas. Creo que eso es casi tan malo como la gente de Rails que usa SQLite para pruebas y PostgreSQL para implementación de producción.
H2 admite algunas extensiones de PostgreSQL y emula el dialecto de PostgreSQL. Sin embargo, es solo eso, una emulación. Encontrará áreas donde H2 acepta una consulta, pero PostgreSQL no, donde se diferencia de comportamiento, etc . También encontrará muchos lugares donde PostgreSQL admite hacer algo que H2 simplemente no puede, como funciones de ventana, al momento de escribir.
Si comprende las limitaciones de este enfoque y su acceso a la base de datos es simple, H2 podría estar bien. Pero en ese caso, probablemente sea un mejor candidato para un ORM que abstraiga la base de datos porque de todos modos no está usando sus características interesantes, y en ese caso, ya no tiene que preocuparse tanto por la compatibilidad de la base de datos.
¡Los espacios de tabla no son la respuesta!
No , no utilizar un espacio de tablas para crear una base de datos "en memoria". No solo es innecesario, ya que de todos modos no ayudará al rendimiento de manera significativa, sino que también es una excelente manera de interrumpir el acceso a cualquier otro que pueda interesarle en la misma instalación de PostgreSQL. La documentación 9.4 ahora contiene la siguiente advertencia :
porque me di cuenta de que demasiadas personas estaban haciendo esto y tenían problemas.
(Si ha hecho esto, puede
mkdir
usar el directorio de espacio de tabla que falta para que PostgreSQL comience de nuevo, luegoDROP
las bases de datos, tablas, etc. faltantes. Es mejor no hacerlo).fuente
initdb
instalar una Pg completamente nueva allí. Pero en realidad, hay poca diferencia entre una página que se ha ajustado para realizar pruebas rápidas en el almacenamiento normal (fsync = off y otras características de durabilidad / seguridad de datos desactivadas) que ejecutarse en un ramdisk, al menos en Linux.O puede crear un TABLESPACE en ramfs / tempfs y crear todos sus objetos allí.
Recientemente me señalaron un artículo sobre cómo hacer exactamente eso en Linux .
Advertencia
Esto puede poner en peligro la integridad de todo su clúster de base de datos .
Lea la advertencia agregada en el manual.
Así que esta es solo una opción para datos fungibles.
Para las pruebas unitarias , debería funcionar bien. Si está ejecutando otras bases de datos en la misma máquina, asegúrese de usar un clúster de base de datos separado (que tiene su propio puerto) para estar seguro.
fuente
initdb
una nueva instancia de postgres en tempfs o ramdisk. No , no utilizar un espacio de tabla en un tempfs etc, es frágil y sin sentido. Es mejor usar un espacio de tabla normal y crearUNLOGGED
tablas; funcionará de manera similar. Y no abordará el rendimiento de WAL y los factores fsync a menos que tome medidas que pongan en riesgo la integridad de toda la base de datos (consulte stackoverflow.com/q/9407442/398670 ). No lo hagas.Ahora es posible ejecutar una instancia en memoria de PostgreSQL en sus pruebas JUnit a través del componente PostgreSQL incrustado de OpenTable: https://github.com/opentable/otj-pg-embedded .
Al agregar la dependencia a la biblioteca otj-pg-embedded ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ) puede iniciar y detener su propia instancia de PostgreSQL en su @Before y @Afer ganchos:
Incluso ofrecen una regla JUnit para que JUnit inicie y detenga automáticamente su servidor de base de datos PostgreSQL:
fuente
@Rule
con@ExtendWith
? Solo usa el.start()
in@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Puede usar TestContainers para activar un contenedor Docker de PosgreSQL para pruebas: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers proporciona un JUnit @ Rule / @ ClassRule : este modo inicia una base de datos dentro de un contenedor antes de sus pruebas y luego la destruye.
Ejemplo:
fuente
Ahora hay una versión en memoria de PostgreSQL de la compañía de búsqueda rusa llamada Yandex: https://github.com/yandex-qatools/postgresql-embedded
Se basa en el proceso de incrustación de Flapdoodle OSS.
Ejemplo de uso (de la página de github):
Lo estoy usando algún tiempo. Funciona bien.
ACTUALIZADO : este proyecto ya no se mantiene activamente
fuente
También puede utilizar las opciones de configuración de PostgreSQL (como las que se detallan en la pregunta y la respuesta aceptada aquí ) para lograr el rendimiento sin tener que recurrir necesariamente a una base de datos en memoria.
fuente
Si está usando NodeJS, puede usar pg-mem (descargo de responsabilidad: soy el autor) para emular las características más comunes de una base de datos de postgres.
Tendrá una base de datos completa en memoria, aislada e independiente de la plataforma que replica el comportamiento de PG (incluso se ejecuta en navegadores ).
Escribí un artículo para mostrar cómo usarlo para tus pruebas unitarias aquí .
fuente