En mis pruebas unitarias, tengo un accesorio que crea una transacción de reversión para limpiar la base de datos después de que se hayan ejecutado mis pruebas. Se ve algo como esto:
(defn with-rollback [test-fn] (let [db-conn (db/connect db/test-pg-db)] (jdbc/with-db-transaction [txn db-conn {:isolation :serializable}] (jdbc/db-set-rollback-only! txn) (-> (mount/only [#'db/db]) (mount/swap {#'db/db txn}) (mount/start)) (test-fn) (mount/stop)) (db/disconnect db-conn))) Luego, en las pruebas que hago (use-fixtures :each fixtures/with-rollback) .
Esto funciona muy bien, excepto en las pruebas en las que quiero probar que las condiciones de error realmente revierten las transacciones. Por ejemplo, quiero probar que cuando falla una solicitud a un servicio externo, no escribo nada en la base de datos.
¿Hay alguna forma de obtener un comportamiento similar a las transacciones anidadas para mi caso de uso? Tuve la idea de anular la función jdbc/db-transaction* con algo que crea puntos de guardado cuando se abre una transacción y retrocede al más cercano cuando se detecta una excepción, pero nunca pude hacerlo funcionar. ¡Agradezco cualquier ayuda!
También estaba luchando con este problema y, finalmente, decidí buscar una solución alternativa para tener archivos separados para pruebas "normales" y pruebas de transacciones. De esta manera es posible utilizar luminarias separadas.
Por lo tanto, usaría un accesorio de reversión para las pruebas normales y un accesorio claro/truncado para las pruebas de transacción. Truncar tiene un mayor costo de rendimiento, por lo tanto, el dispositivo debe usarse con moderación.
Aquí está la implementación del accesorio truncado. Se supone que el esquema utilizado es public y que hay algunos datos almacenados sobre las migraciones de la base de datos en una tabla schema_migrations que debe dejarse intacta.
(defn truncate-db [tests] (tests) (jdbc/execute! db-conn "DO $$ BEGIN EXECUTE 'TRUNCATE TABLE ' || (SELECT string_agg(table_name::text, ',') FROM information_schema.tables WHERE table_schema = 'public' AND table_type = 'BASE TABLE' AND table_name != 'schema_migrations') || ' CASCADE'; END; $$;"))