Друкарня від WE.UA

𝗦𝗽𝗿𝗶𝗻𝗴 𝗕𝗼𝗼𝘁 𝗧𝗲𝘀𝘁𝗝𝗮𝗿𝘀, або викинь 𝗗𝗼𝗰𝗸𝗲𝗿 для написання інтеграційних тестів!

Пролог

Южуал девелопер у 25 років

Усміхаєшся, коли чуєш “інтеграційні тести”? Ну звісно: знову треба піднімати десяток сервісів у Docker, а лептоп при цьому перетворюється на обігрівач, усе гальмує, шумить і гріється.

А що як я скажу, що є альтернатива Docker? 🤔

Ще у 2024 році Josh Long презентував Spring Boot Testjars — експериментальну фічу, яка дозволяє запускати Spring Boot-додатки прямо з Java-тестів. Без Docker. Круто? Ще б пак! Але не все так ідеально — Testjars ще в експериментальній фазі, не вистачає багатьох речей, але основне вже працює, і це відкриває цікаві можливості.

Епіграф

Я, натхненний цією ідеєю, написав невеличкий pet-проєкт, щоб показати, як Testjars працює на практиці.

Маю два сервіси:

  • 📚 bookshelf — простий CRUD-додаток, який буде запускатись як окремий jar у тестах;

  • 🔁 demotestjars — сервіс-проксі до bookshelf, який використовує Feign-клієнт для взаємодії.

Як це працює

Спершу нам треба зібрати bookshelf як .jar, придатний для запуску з тестів. Просто зарань mvn clean install 😊

Крок 1: Додаємо залежності

<dependency>
  <groupId>org.springframework.experimental.boot</groupId>
  <artifactId>spring-boot-testjars</artifactId>
  <version>0.0.4</version>
  <scope>test</scope>
</dependency>

 <dependency>
  <groupId>org.springframework.experimental.boot</groupId>
  <artifactId>spring-boot-testjars-maven</artifactId>
  <version>0.0.4</version>
</dependency>

Крок 2: Створюємо проперті файл для bookshelf

server.port=18083

spring.datasource.url=jdbc:h2:tcp://localhost:9092/mem:bookshelf
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

💡 Ми використовуємо H2 замість реальної БД — якраз реальний кейс з життя

Крок 3: Конфігуруємо запуск bookshelf у тестах

  @Bean
  static CommonsExecWebServerFactoryBean bookShelfServer() {
    return CommonsExecWebServerFactoryBean.builder()
        .useRandomPort(false)
        .classpath(cp -> cp
            .entries(
                new MavenClasspathEntry("com.example:bookshelf:0.0.1-SNAPSHOT"),
                new MavenClasspathEntry("com.h2database:h2:2.3.232"),
                new ResourceClasspathEntry("book-shelf.properties", "application.properties")
                )
        );
  }

І все! Тепер bookshelf запускається як окремий Spring Boot сервіс просто у вашому інтеграційному тесті — без Docker і YAML’ів.

Що бачимо у логах

Коли запускаєш тести, бачиш логи не лише основного застосунку (demotestjars), а й запущеного bookshelf — як у справжньому інтеграційному середовищі. Жодного Docker.

2025-05-11T23:26:05.517+03:00  INFO 4312 --- [demotestjars] [o-auto-1-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-05-11T23:26:05.518+03:00  INFO 4312 --- [demotestjars] [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2025-05-11T23:26:05.518+03:00  INFO 4312 --- [demotestjars] [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] ---> POST http://localhost:18083/api/books HTTP/1.1
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] Content-Length: 78
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] Content-Type: application/json
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] 
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] {"id":null,"title":"Test Driven Development","author":"Kent Beck","year":2003}
2025-05-11T23:26:05.556+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] ---> END HTTP (78-byte body)
2025-05-11T23:26:05.589+03:00  INFO 4316 --- [bookshelf] [io-18083-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-05-11T23:26:05.590+03:00  INFO 4316 --- [bookshelf] [io-18083-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2025-05-11T23:26:05.590+03:00  INFO 4316 --- [bookshelf] [io-18083-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
2025-05-11T23:26:05.655+03:00  INFO 4316 --- [bookshelf] [io-18083-exec-1] c.example.bookshelf.service.BookService  : save Book: Book(id=null, title=Test Driven Development, author=Kent Beck, year=2003)
Hibernate: insert into book (author,title,created_year,id) values (?,?,?,default)
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] <--- HTTP/1.1 200 (179ms)
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] connection: keep-alive
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] content-type: application/json
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] date: Sun, 11 May 2025 20:26:05 GMT
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] keep-alive: timeout=60
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] transfer-encoding: chunked
2025-05-11T23:26:05.736+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] 
2025-05-11T23:26:05.737+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] {"id":1,"title":"Test Driven Development","author":"Kent Beck","year":2003}
2025-05-11T23:26:05.737+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-1] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#addBook] <--- END HTTP (75-byte body)
2025-05-11T23:26:05.782+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] ---> GET http://localhost:18083/api/books HTTP/1.1
2025-05-11T23:26:05.782+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] ---> END HTTP (0-byte body)
2025-05-11T23:26:05.784+03:00  INFO 4316 --- [bookshelf] [io-18083-exec-2] c.example.bookshelf.service.BookService  : get All Books
Hibernate: select b1_0.id,b1_0.author,b1_0.title,b1_0.created_year from book b1_0
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] <--- HTTP/1.1 200 (67ms)
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] connection: keep-alive
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] content-type: application/json
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] date: Sun, 11 May 2025 20:26:05 GMT
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] keep-alive: timeout=60
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] transfer-encoding: chunked
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] 
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] [{"id":1,"title":"Test Driven Development","author":"Kent Beck","year":2003}]
2025-05-11T23:26:05.850+03:00 DEBUG 4312 --- [demotestjars] [o-auto-1-exec-2] c.d.demotestjars.client.BookShelfClient  : [BookShelfClient#getAllBooks] <--- END HTTP (77-byte body)
2025-05-11T23:26:05.903+03:00  INFO 4312 --- [demotestjars] [ionShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : Commencing graceful shutdown. Waiting for active requests to complete
2025-05-11T23:26:05.905+03:00  INFO 4312 --- [demotestjars] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : Graceful shutdown complete
2025-05-11T23:26:05.906+03:00  INFO 4312 --- [demotestjars] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2025-05-11T23:26:05.911+03:00  INFO 4312 --- [demotestjars] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Мінуси (поки що)

Testjars має потенціал, але поки не все працює як хочеться:

1. Не працює анотація @DynamicProperty

Ця фіча також є в документації, але в реальному житті вона поки що не працює. Подробиці:
https://github.com/spring-projects-experimental/spring-boot-testjars?tab=readme-ov-file#dynamicproperty

Епілог

Чи зможе Testjars замінити Docker? Повноцінно — ні. Адже Postgres, Oracle чи Redis у вигляді jar-файлів ти не запустиш. Але якщо тобі треба інтегрувати лише власні мікросервіси — це класне рішення.

Особливо, якщо ти працюєш на віртуалці або слабкому ноуті, де Docker — це біль.

Testjars ще сирий, але вже зараз економить купу нервів. А в майбутньому — можливо, стане стандартом.

🔗 Посилання на репозиторії:

Хочеш мене підтримати підписуйся на мій патреон:

https://www.patreon.com/c/serhiibarabash

Список джерел
  1. Spring Tips: Spring Boot Testjars

Статті про вітчизняний бізнес та цікавих людей:

  • Як побудована програма Meest China Academy

    Курс про товарний бізнес охоплює різні етапи роботи: від пошуку ідеї до перевірки товару, логістики та масштабування. Програма Meest China Academy містить 17 модулів, які послідовно розкривають ці теми без зведення всього навчання до однієї універсальної поради.

    Теми цього довгочиту:

    Meest
  • Які технології використані в Айфон 17

    Айфон 17 поєднує OLED-дисплей із частотою до 120 Гц, чип A19, дві камери Fusion 48 Мп і швидке заряджання через USB-C. У COMFY можна купити Айфон 17 з накопичувачем на 256 або 512 ГБ, вибравши конфігурацію відповідно до обсягу фото, відео та застосунків

    Теми цього довгочиту:

    Iphone 17
  • Як вибрати вживаний iPhone: коротке керівництво для розумної покупки

    Вторинний ринок смартфонів Apple активно зростає, і питання, як вибрати вживаний iPhone, стає актуальним для дедалі більшої кількості користувачів. Правильний підхід дозволяє отримати бу iPhone з актуальною iOS і доброю камерою за помітно нижчу ціну, ніж у нових пристроїв.

    Теми цього довгочиту:

    Iphone
  • Як подолати жіночу безплідність за допомогою донорських яйцеклітин

    Діагноз "безпліддя" рідко звучить як вирок одразу. Для багатьох жінок саме в цей момент вперше звучить словосполучення "донорські яйцеклітини" — і це часто не кінець шляху до материнства, а якраз новий, реальний шанс.

    Теми цього довгочиту:

    Донорство
  • Як заспокоїти зубний біль і чому самолікування може призвести до операції?

    Раптовий біль у зубі може призвести до порушення сну та ускладненого вживання їжі. Люди часто приймають таблетки, роблять полоскання або лікуються народними засобами. В таких випадках не варто відкладати візит до стоматолога, адже можуть з’явитись ускладнення.

    Теми цього довгочиту:

    Стоматологія
Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Сергій Барабаш
Сергій Барабаш@sbarabash

5Довгочити
759Перегляди
13Підписники
На Друкарні з 30 березня 2024

Більше від автора

Це також може зацікавити:

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Це також може зацікавити: