Profile Spring są metodą kontroli sposobu budowania kontekstu aplikacji. Określają one, które fasole i wartości konfiguracyjne są używane przez kontener wstrzykiwania zależności do konfiguracji aplikacji. Korzystanie z profili umożliwia programistom i administratorom zmianę konfiguracji aplikacji za pomocą jednego przełącznika.

Testy integracyjne

Jednym z obszarów, w których profile mogą być szczególnie przydatne, są testy integracyjne. Testy integracyjne, jak sama nazwa wskazuje, służą do sprawdzania, czy komponenty systemu współpracują ze sobą, tj. współdziałają zgodnie z oczekiwaniami. Jednymi z takich komponentów są bazy danych, serwery pocztowe, systemy rozliczeniowe czy ogólnie usługi zewnętrzne. Czasami nie chcemy uruchamiać naszych testów przeciwko tym systemom, aby uniknąć niepotrzebnych lub nawet szkodliwych efektów ubocznych naszych testów. Innym częstym powodem jest przyspieszenie kompilacji na maszynach deweloperów, ale dokładne uruchomienie testów w środowiskach CI/CD. Poza tym może to również pomóc w uczynieniu ich deterministycznymi. Wygodnym narzędziem do tego są profile Spring.

Dlaczego testy integracyjne wymagają określonego profilu?

W jednym z naszych projektów chcieliśmy skonfigurować kontekst wszystkich testów integracyjnych nieco inaczej niż w aplikacji produkcyjnej, tj. musieliśmy zmienić adres url bazy danych używanej do tych testów i, co ważniejsze, chcieliśmy wyczyścić dane za pomocą liquibase. Chodzi o ustawienie następujących właściwości:

spring.datasource.url=jdbc:postgresql://localhost:5432/db-integration-tests
spring.liquibase.drop-first=true

Oczywistym rozwiązaniem było użycie profili Spring i niestandardowego pliku właściwości, ponieważ Spring czyta m.in, application-{profile}.properties plik, w którym profile jest nazwą aktualnie aktywnego profilu. Następnie Spring zawsze łączy go z application.properties (pierwszy zastępuje drugi). Zdecydowaliśmy więc, że wszystkie testy Spring będą uruchamiane z test profil.

Ustawienie test profil

Istnieje kilka sposobów na skonfigurowanie aktywnych profili w testach opartych na Spring:

spring-profile-for-tests

  • Konfigurowanie IDE do aktywacji test profil - działa i jest elastyczny, ale wymaga ręcznej konfiguracji na komputerze każdego dewelopera
  • @TestPropertySource - działa, ale wymaga oznaczenia wszystkich testów tą adnotacją lub dziedziczenia po nadklasie posiadającej tę adnotację. W naszym przypadku nie chcieliśmy wprowadzać takiego dziedziczenia i ograniczać się.
  • @ActiveProfiles - wymaga również oznaczenia wszystkich testów tą adnotacją lub dziedziczenia z superklasy posiadającej tę adnotację. Poza tym ma jeszcze jedną poważną wadę: jest ostateczna, tj. profile Spring przekazywane przez zmienne środowiskowe są ignorowane, ponieważ jest to priorytet. Jeśli chcesz aktywować inny profil za pomocą wiersza poleceń lub IDE, nie masz już opcji... prawie. Jest jeden sposób: możesz napisać własny ActiveProfilesResolver która pobierze zmienne środowiskowe przed wartościami wprowadzonymi w @ActiveProfiles adnotacja. Możesz nawet zobaczyć działające rozwiązanie tutaj. Zapewnia najlepszą elastyczność, ale wiąże się z kosztami utrzymania dodatkowego kodu.
  • application.properties w testowej bazie kodu - możemy po prostu umieścić spring.profile.active=test w tym pliku, a wszystkie testy integracyjne będą odbierać ten profil, ale także będą respektować nadpisanie aktywnych profili z wiersza poleceń. Brzmi dobrze, prawda? Nie do końca. Problem polega na tym, że to zacienia application.properties z głównej bazy kodu (która zwykle przechowuje domyślne wartości konfiguracyjne dla aplikacji), więc aby było to użyteczne, musiałbyś skopiować i utrzymywać oba pliki w synchronizacji, z wyłączeniem ustawień specyficznych dla testu, co czyni to jeszcze trudniejszym.
  • profil domyślny - gdy Spring uruchamia kontekst aplikacji bez jawnie ustawionych profili, zgłasza interesującą rzecz:

spring-default-profile

Spada z powrotem do default profil. Jest to nieco mylące, ponieważ kiedy bierzemy Środowisko fasola i zadzwoń getActiveProfiles() otrzymujemy pustą tablicę, ale default profil jest jednak aktywny i można używać application-default.properties! Możemy więc użyć go jako dodatkowego application.properties i umieścić tutaj ustawienia specyficzne dla testów. W przypadku plików właściwości prawdopodobnie odpowiadałoby to naszym potrzebom, ale gdy używamy alternatywnych beanów do testów, musimy oznaczyć fałszywe implementacje za pomocą @Profile("test"). Wyglądałoby to źle i wprowadzałoby w błąd @Profile("default"). Ponadto, w mojej osobistej opinii application-test.properties jest pierwszym wyborem do sprawdzania wartości konfiguracyjnych dla testów. Dlatego zdecydowaliśmy się aktywować test profil w application-default.properties:

spring.profiles.active=test

Teraz możemy użyć application-test.properties jako domyślna konfiguracja dla testów integracyjnych, ale jeśli zdecydujesz się zmienić profil lub dodać jeszcze jeden, możesz to zrobić.

Wnioski

Jak widać przy użyciu default umożliwia zmianę domyślnego profilu dla testów integracyjnych z następującymi korzyściami:

  • nie ma potrzeby wprowadzania dodatkowego dziedziczenia
  • możliwość zastępowania aktywnych profili za pomocą profili środowiskowych
  • brak dodatkowego kodu do utrzymania

Chcesz porozmawiać z naszymi ekspertami o niestandardowych rozwiązaniach w zakresie tworzenia oprogramowania dla Twojej firmy?

P: Czym są profile Spring?

O: Profile Spring są metodą kontrolowania sposobu budowania kontekstu aplikacji. Określają one, które ziarna i wartości konfiguracyjne są używane przez kontener wstrzykiwania zależności do skonfigurowania aplikacji. Korzystanie z profili umożliwia programistom i administratorom zmianę konfiguracji aplikacji za pomocą jednego przełącznika.

P: Czym są testy integracyjne i dlaczego wymagają określonych profili?

O: Testy integracyjne służą do sprawdzania, czy komponenty systemu współpracują ze sobą, takie jak bazy danych, serwery pocztowe, systemy rozliczeniowe lub usługi zewnętrzne. Czasami nie chcemy uruchamiać naszych testów przeciwko tym systemom, aby uniknąć niepotrzebnych lub nawet szkodliwych efektów ubocznych naszych testów. Profile Spring są wygodnym narzędziem do konfigurowania kontekstu testów integracyjnych inaczej niż w przypadku aplikacji produkcyjnej, np. zmieniając adres URL bazy danych używanej do testów lub czyszcząc dane.

4.9/5 - (159 głosów)