Saya ingin menjalankan database PostgreSQL kecil yang hanya berjalan di memori, untuk setiap pengujian unit yang saya tulis. Misalnya:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
Idealnya saya akan memiliki satu postgres yang dapat dieksekusi diperiksa ke kontrol versi, yang akan digunakan pengujian unit.
Sesuatu seperti HSQL
, tapi untuk postgres. Bagaimana saya bisa melakukan itu?
Apakah saya bisa mendapatkan versi Postgres seperti itu? Bagaimana saya bisa menginstruksikannya untuk tidak menggunakan disk?
testcontainers
, yang pada dasarnya memungkinkan pengujian Anda memulai dengan sekali pakai, galangan, postgres-contoh. Lihat github.com/testcontainers/testcontainers-java/blob/master/…(Memindahkan jawaban saya dari Menggunakan PostgreSQL dalam memori dan menggeneralisasikannya):
Anda tidak dapat menjalankan Pg dalam proses, dalam memori
Tidak, tidak mungkin. PostgreSQL diimplementasikan dalam C dan dikompilasi ke kode platform. Tidak seperti H2 atau Derby, Anda tidak bisa hanya memuat
jar
dan menjalankannya sebagai DB dalam memori sekali pakai.Tidak seperti SQLite, yang juga ditulis dalam C dan dikompilasi ke kode platform, PostgreSQL juga tidak dapat dimuat dalam proses. Ini membutuhkan banyak proses (satu per koneksi) karena ini adalah arsitektur multiprosesing, bukan multithreading. Persyaratan multiprosesing berarti Anda harus meluncurkan postmaster sebagai proses yang berdiri sendiri.
Sebagai gantinya: prakonfigurasi koneksi
Saya sarankan cukup menulis pengujian Anda untuk mengharapkan nama host / nama pengguna / kata sandi tertentu berfungsi, dan memiliki pengujian memanfaatkan
CREATE DATABASE
database sekali pakai, laluDROP DATABASE
di akhir proses. Dapatkan detail koneksi database dari file properti, buat properti target, variabel lingkungan, dll.Aman untuk menggunakan instance PostgreSQL yang sudah ada yang sudah memiliki database yang Anda minati, selama pengguna yang Anda masukkan ke pengujian unit bukan superuser, hanya pengguna yang memiliki
CREATEDB
hak. Paling buruk Anda akan membuat masalah kinerja di database lain. Saya lebih suka menjalankan instalasi PostgreSQL yang sepenuhnya terisolasi untuk pengujian karena alasan itu.Sebagai gantinya: Luncurkan instance PostgreSQL sekali pakai untuk pengujian
Bergantian, jika Anda benar - benar ingin Anda dapat meminta harness pengujian Anda menemukan binari
initdb
andpostgres
, menjalankaninitdb
untuk membuat database, memodifikasipg_hba.conf
ketrust
, menjalankanpostgres
untuk memulainya di port acak, membuat pengguna, membuat DB, dan menjalankan pengujian . Anda bahkan dapat memaketkan binari PostgreSQL untuk beberapa arsitektur dalam jar dan mengekstrak yang untuk arsitektur saat ini ke direktori sementara sebelum menjalankan pengujian.Secara pribadi saya pikir itu adalah rasa sakit besar yang harus dihindari; jauh lebih mudah untuk hanya mengonfigurasi DB pengujian. Namun, ini menjadi sedikit lebih mudah dengan munculnya
include_dir
dukungan dalampostgresql.conf
; sekarang Anda bisa menambahkan satu baris, lalu menulis file konfigurasi yang dihasilkan untuk yang lainnya.Pengujian lebih cepat dengan PostgreSQL
Untuk informasi lebih lanjut tentang cara aman meningkatkan kinerja PostgreSQL untuk tujuan pengujian, lihat jawaban rinci saya menulis tentang topik ini sebelumnya: Optimalkan PostgreSQL untuk pengujian cepat
Dialek PostgreSQL H2 bukanlah pengganti yang sebenarnya
Beberapa orang malah menggunakan database H2 dalam mode dialek PostgreSQL untuk menjalankan tes. Saya pikir itu hampir seburuk orang-orang Rails yang menggunakan SQLite untuk pengujian dan PostgreSQL untuk penerapan produksi.
H2 mendukung beberapa ekstensi PostgreSQL dan mengemulasi dialek PostgreSQL. Namun, itu hanya itu - sebuah persaingan. Anda akan menemukan area di mana H2 menerima kueri tetapi PostgreSQL tidak, di mana perilakunya berbeda, dll . Anda juga akan menemukan banyak tempat di mana PostgreSQL mendukung melakukan sesuatu yang tidak bisa dilakukan H2 - seperti fungsi jendela, pada saat penulisan.
Jika Anda memahami batasan pendekatan ini dan akses database Anda sederhana, H2 mungkin OK. Tetapi dalam hal ini Anda mungkin adalah kandidat yang lebih baik untuk ORM yang mengabstraksi database karena Anda tidak menggunakan fitur-fiturnya yang menarik - dan dalam hal ini, Anda tidak perlu terlalu peduli tentang kompatibilitas database lagi.
Tablespaces bukanlah jawabannya!
Jangan tidak menggunakan tablespace untuk membuat "di memori database". Tidak hanya itu tidak diperlukan karena itu tidak akan membantu kinerja secara signifikan, tetapi juga cara yang bagus untuk mengganggu akses ke orang lain yang mungkin Anda pedulikan dalam instalasi PostgreSQL yang sama. Dokumentasi 9.4 sekarang berisi peringatan berikut :
karena saya perhatikan terlalu banyak orang yang melakukan ini dan mengalami masalah.
(Jika Anda telah melakukan ini, Anda dapat
mkdir
membuka direktori tablespace yang hilang untuk menjalankan PostgreSQL lagi, laluDROP
database yang hilang, tabel, dll. Lebih baik tidak melakukannya.)sumber
initdb
menginstal Pg baru di sana. Tapi sungguh, ada sedikit perbedaan antara Pg yang di-tweak untuk pengujian cepat pada penyimpanan normal (fsync = off dan fitur ketahanan / keamanan data lainnya dimatikan) daripada berjalan di ramdisk, setidaknya di Linux.Atau Anda bisa membuat TABLESPACE di ramfs / tempfs dan membuat semua objek Anda di sana.
Baru-baru ini saya diarahkan ke sebuah artikel tentang melakukan hal itu di Linux .
Peringatan
Ini dapat membahayakan integritas seluruh cluster database Anda .
Baca peringatan tambahan di manual.
Jadi ini hanya opsi untuk data yang dapat dibuang.
Untuk pengujian unit seharusnya berfungsi dengan baik. Jika Anda menjalankan database lain di mesin yang sama, pastikan untuk menggunakan cluster database terpisah (yang memiliki portnya sendiri) agar aman.
sumber
initdb
instance postgres baru di tempfs atau ramdisk. Jangan tidak menggunakan tablespace di sebuah tempfs dll, itu rapuh dan sia-sia. Anda lebih baik menggunakan tablespace normal dan membuatUNLOGGED
tabel - ini akan bekerja sama. Dan itu tidak akan membahas kinerja WAL dan faktor fsync kecuali Anda mengambil tindakan yang akan mempertaruhkan integritas dari seluruh DB (lihat stackoverflow.com/q/9407442/398670 ). Jangan lakukan itu.Sekarang dimungkinkan untuk menjalankan instance dalam memori dari PostgreSQL dalam pengujian JUnit Anda melalui Komponen PostgreSQL Tertanam dari OpenTable: https://github.com/opentable/otj-pg-embedded .
Dengan menambahkan dependensi ke pustaka tertanam otj-pg ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ) Anda dapat memulai dan menghentikan instance PostgreSQL Anda sendiri di @Before dan @Afer kait:
Mereka bahkan menawarkan aturan JUnit agar JUnit secara otomatis memulai dan menghentikan server database PostgreSQL untuk Anda:
sumber
@Rule
dengan@ExtendWith
? Hanya menggunakan.start()
di@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Anda dapat menggunakan TestContainers untuk menjalankan kontainer buruh pelabuhan PosgreSQL untuk pengujian: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers menyediakan JUnit @ Rule / @ ClassRule : mode ini memulai database di dalam container sebelum pengujian Anda dan menghentikannya setelahnya.
Contoh:
sumber
Sekarang ada versi dalam memori PostgreSQL dari perusahaan Pencarian Rusia bernama Yandex: https://github.com/yandex-qatools/postgresql-embedded
Ini didasarkan pada proses penyematan Flapdoodle OSS.
Contoh penggunaan (dari halaman github):
Saya menggunakannya beberapa saat. Ini bekerja dengan baik.
DIPERBARUI : proyek ini tidak lagi dipertahankan secara aktif
sumber
Anda juga dapat menggunakan pengaturan konfigurasi PostgreSQL (seperti yang dijelaskan dalam pertanyaan dan jawaban yang diterima di sini ) untuk mencapai kinerja tanpa harus menggunakan database dalam memori.
sumber
Jika Anda menggunakan NodeJS, Anda dapat menggunakan pg-mem (disclaimer: I'm the author) untuk meniru fitur paling umum dari sebuah postgres db.
Anda akan memiliki basis data penuh dalam memori, terisolasi, platform-agnostik yang mereplikasi perilaku PG (bahkan berjalan di browser ).
Saya menulis artikel untuk menunjukkan cara menggunakannya untuk pengujian unit Anda di sini .
sumber