Chcę uruchomić małą bazę danych PostgreSQL, która działa tylko w pamięci, dla każdego testu jednostkowego, który piszę. Na przykład:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
Najlepiej byłoby, gdyby pojedynczy plik wykonywalny postgres został wpisany do kontroli wersji, którego użyje test jednostkowy.
Coś jak HSQL
, ale dla postgresów. Jak mogę to zrobić?
Czy mogę dostać taką wersję Postgres? Jak mogę poinstruować go, aby nie korzystał z dysku?
testcontainers
platformy docker jest powszechne, niektórym osobom udało się zastosować takie narzędzie , które zasadniczo pozwala testowemu uruchomieniu na jednorazową, zadokeryzowaną instancję postgres. Zobacz github.com/testcontainers/testcontainers-java/blob/master/…(Przenoszę moją odpowiedź z używania PostgreSQL w pamięci i generalizuję ją):
Nie możesz uruchomić Pg w trakcie, w pamięci
Nie, to niemożliwe. PostgreSQL jest zaimplementowany w C i skompilowany do kodu platformy. W przeciwieństwie do H2 lub Derby nie można po prostu załadować
jar
i uruchomić go jako jednorazowej bazy danych w pamięci.W przeciwieństwie do SQLite, który jest również napisany w C i skompilowany do kodu platformy, PostgreSQL również nie może być ładowany w procesie. Wymaga wielu procesów (po jednym na połączenie), ponieważ jest to architektura wieloprocesowa, a nie wielowątkowa. Wymóg wieloprocesorowości oznacza, że musisz uruchomić postmastera jako samodzielny proces.
Zamiast tego: skonfiguruj wstępnie połączenie
Proponuję po prostu napisać testy, aby oczekiwać, że określona nazwa hosta / nazwa użytkownika / hasło zadziała, a test zaprzęgnie
CREATE DATABASE
do jednorazowej bazy danych, a następnieDROP DATABASE
pod koniec uruchomienia. Uzyskaj szczegóły połączenia z bazą danych z pliku właściwości, właściwości celu kompilacji, zmiennej środowiskowej itp.Bezpiecznie jest używać istniejącej instancji PostgreSQL, w której masz już bazy danych, na których Ci zależy, o ile użytkownik, którego dostarczasz do testów jednostkowych, nie jest superużytkownikiem, tylko użytkownikiem z
CREATEDB
uprawnieniami. W najgorszym przypadku wystąpią problemy z wydajnością w innych bazach danych. Z tego powodu wolę uruchomić całkowicie izolowaną instalację PostgreSQL do testów.Zamiast tego: uruchom jednorazową instancję PostgreSQL do testowania
Alternatywnie, jeśli naprawdę chcesz, możesz poprosić swoją wiązkę testową, aby zlokalizowała pliki binarne
initdb
ipostgres
, uruchom ją,initdb
aby utworzyć bazę danych, zmodyfikujpg_hba.conf
jątrust
, uruchompostgres
ją na losowym porcie, utwórz użytkownika, utwórz bazę danych i uruchom testy . Możesz nawet spakować pliki binarne PostgreSQL dla wielu architektur w jednym pliku jar i rozpakować te dla bieżącej architektury do katalogu tymczasowego przed uruchomieniem testów.Osobiście uważam, że jest to poważny ból, którego należy unikać; o wiele łatwiej jest po prostu skonfigurować testową bazę danych. Jednak stało się to trochę łatwiejsze wraz z pojawieniem się
include_dir
wsparcia wpostgresql.conf
; teraz możesz po prostu dodać jedną linię, a następnie napisać wygenerowany plik konfiguracyjny dla całej reszty.Szybsze testowanie z PostgreSQL
Aby uzyskać więcej informacji o tym, jak bezpiecznie poprawić wydajność PostgreSQL do celów testowych, zobacz szczegółową odpowiedź, którą napisałem wcześniej na ten temat: Optymalizuj PostgreSQL do szybkiego testowania
Dialekt H2 w PostgreSQL nie jest prawdziwym zamiennikiem
Niektórzy zamiast tego używają bazy danych H2 w trybie dialektu PostgreSQL do uruchamiania testów. Myślę, że to prawie tak złe, jak ludzie z Railsów używający SQLite do testowania i PostgreSQL do wdrożeń produkcyjnych.
H2 obsługuje niektóre rozszerzenia PostgreSQL i emuluje dialekt PostgreSQL. Jednak to tylko to - emulacja. Znajdziesz obszary, w których H2 akceptuje zapytanie, a PostgreSQL nie, gdzie zachowanie jest inne itp . Znajdziesz również wiele miejsc, w których PostgreSQL obsługuje robienie czegoś, czego H2 po prostu nie może - na przykład funkcji okna w momencie pisania.
Jeśli rozumiesz ograniczenia tego podejścia, a dostęp do bazy danych jest prosty, H2 może być w porządku. Ale w takim przypadku prawdopodobnie jesteś lepszym kandydatem na ORM, który abstrahuje bazę danych, ponieważ i tak nie używasz jej interesujących funkcji - iw takim przypadku nie musisz już tak bardzo dbać o zgodność bazy danych.
Przestrzenie tabel nie są odpowiedzią!
Czy nie używać tabel do tworzenia bazy danych „w pamięci”. Nie tylko jest to niepotrzebne, ponieważ i tak nie poprawi wydajności w znaczący sposób, ale jest to również świetny sposób na zakłócenie dostępu do każdego innego, na którym może Ci zależeć w tej samej instalacji PostgreSQL. Dokumentacja 9.4 zawiera teraz następujące ostrzeżenie :
ponieważ zauważyłem, że zbyt wielu ludzi to robi i ma kłopoty.
(Jeśli to zrobiłeś, możesz
mkdir
brakować katalog obszaru tabel, aby PostgreSQL zaczął się od nowa, a następnieDROP
brakujące bazy danych, tabele itp. Lepiej po prostu tego nie robić.)źródło
initdb
zainstalować tam całkiem nową instalację Pg. Ale tak naprawdę istnieje niewielka różnica między Pg, który został dostosowany do szybkiego testowania w normalnej pamięci masowej (fsync = off i inne funkcje związane z trwałością / bezpieczeństwem danych wyłączone) a działaniem na ramdysku, przynajmniej w systemie Linux.Lub możesz stworzyć TABLESPACE w ramfs / tempfs i tam utworzyć wszystkie swoje obiekty.
Niedawno wskazano mi artykuł o tym, jak robić dokładnie to w systemie Linux .
Ostrzeżenie
Może to zagrozić integralności całego klastra bazy danych .
Przeczytaj dodane ostrzeżenie w instrukcji.
Jest to więc tylko opcja dla danych, które można wykorzystać.
W przypadku testów jednostkowych powinno działać dobrze. Jeśli używasz innych baz danych na tym samym komputerze, upewnij się, że używasz oddzielnego klastra bazy danych (który ma własny port), aby zachować bezpieczeństwo.
źródło
initdb
nowa instancja postgres w tempfs lub ramdysku. Czy nie używać tabel w sposób tempfs etc, jest kruchy i bezcelowe. Lepiej jest używać normalnego obszaru tabel i tworzeniaUNLOGGED
tabel - będzie to działać podobnie. I nie zajmie się wydajnością WAL i czynnikami fsync, chyba że podejmiesz działania, które zagrozią integralności całej bazy danych (patrz stackoverflow.com/q/9407442/398670 ). Nie rób tego.Teraz można uruchomić instancję PostgreSQL w pamięci w testach JUnit za pośrednictwem wbudowanego komponentu PostgreSQL z OpenTable: https://github.com/opentable/otj-pg-embedded .
Dodając zależność do biblioteki otj-pg-embedded ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ) możesz uruchamiać i zatrzymywać własne wystąpienie PostgreSQL w swoim @Before i Haczyki @Afer:
Oferują nawet regułę JUnit, która automatycznie uruchamia i zatrzymuje serwer bazy danych PostgreSQL dla JUnit:
źródło
@Rule
z@ExtendWith
? Po prostu użyj.start()
w@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Możesz użyć TestContainers, aby uruchomić kontener Docker PosgreSQL do testów: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers zapewniają JUnit @ Rule / @ ClassRule : ten tryb uruchamia bazę danych w kontenerze przed testami, a następnie rozrywa ją.
Przykład:
źródło
Dostępna jest teraz wersja PostgreSQL w pamięci rosyjskiej firmy Yandex: https://github.com/yandex-qatools/postgresql-embedded
Jest oparty na procesie osadzania Flapdoodle OSS.
Przykład użycia (ze strony github):
Używam go od jakiegoś czasu. To dobrze działa.
AKTUALIZACJA : ten projekt nie jest już aktywnie zarządzany
źródło
Możesz także użyć ustawień konfiguracyjnych PostgreSQL (takich jak te wyszczególnione w pytaniu i zaakceptowana odpowiedź tutaj ), aby osiągnąć wydajność bez konieczności uciekania się do bazy danych w pamięci.
źródło
Jeśli używasz NodeJS, możesz użyć pg-mem (zastrzeżenie: jestem autorem), aby emulować najbardziej typowe cechy bazy danych postgres.
Będziesz mieć pełną w pamięci, izolowaną, niezależną od platformy bazę danych replikującą zachowanie PG ( działa nawet w przeglądarkach ).
Napisałem artykuł, aby pokazać, jak go używać do testów jednostkowych tutaj .
źródło