اختبار التكامل لـ Kotlin مع Docker: من الألف إلى الياء
\n\nفي التطوير الحديث باستخدام Kotlin، أصبح اختبار التكامل باستخدام Docker المعيار الفعلي. تتيح الحاويات إنشاء بيئات اختبار معزولة وقابلة للتكرار قريبة جدًا من بيئة الإنتاج. في هذه المقالة، سنستعرض العملية الكاملة لإعداد وكتابة اختبارات التكامل لتطبيقات Kotlin باستخدام Docker ومكتبة Testcontainers.
\n\nلماذا يعتبر Docker مهمًا لاختبار التكامل في Kotlin؟
\n\nغالبًا ما تعاني اختبارات التكامل التقليدية من مشاكل تتعلق بالبيئة: إصدارات مختلفة من قواعد البيانات، عدم توافق برامج التشغيل، اختبارات "عائمة" بسبب العمليات الخلفية. يحل Docker هذه المشاكل من خلال توفير:
\n\n- \n
- العزل: يتم تشغيل كل اختبار في حاوية نظيفة \n
- قابلية التكرار: نفس البيئة على أي جهاز \n
- قابلية التوسع: إمكانية اختبار بنى الخدمات المصغرة المعقدة \n
- السرعة: بدء وإيقاف الحاويات بسرعة \n
إعداد مشروع Kotlin لاختبارات التكامل مع Docker
\n\nللبدء، سنضيف التبعيات اللازمة في ملف build.gradle.kts:
dependencies {\n // Testcontainers\n testImplementation("org.testcontainers:testcontainers:1.19.3")\n testImplementation("org.testcontainers:postgresql:1.19.3")\n testImplementation("org.testcontainers:kafka:1.19.3")\n testImplementation("org.testcontainers:junit-jupiter:1.19.3")\n \n // قاعدة البيانات\n testImplementation("org.postgresql:postgresql:42.7.1")\n \n // JUnit 5\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")\n \n // لتطبيقات Spring Boot\n testImplementation("org.springframework.boot:spring-boot-starter-test:3.2.1")\n testImplementation("org.springframework.boot:spring-boot-testcontainers:3.2.1")\n}\n\nمثال أساسي: الاختبار مع PostgreSQL
\n\nلننظر إلى مثال بسيط - اختبار مستودع يعمل مع PostgreSQL. سننشئ اختبار تكامل باستخدام Testcontainers:
\n\nimport org.junit.jupiter.api.Test\nimport org.testcontainers.containers.PostgreSQLContainer\nimport org.testcontainers.junit.jupiter.Container\nimport org.testcontainers.junit.jupiter.Testcontainers\nimport javax.sql.DataSource\n\n@Testcontainers\nclass UserRepositoryIntegrationTest {\n\n companion object {\n @Container\n val postgres = PostgreSQLContainer<Nothing>("postgres:15-alpine").apply {\n withDatabaseName("testdb")\n withUsername("test")\n withPassword("test")\n }\n }\n\n @Test\n fun `should save and find user`() {\n val dataSource = createDataSource(postgres)\n val repository = UserRepository(dataSource)\n \n val user = User(id = null, name = "إيفان بيتروف", email = "ivan@example.com")\n val savedUser = repository.save(user)\n \n val foundUser = repository.findById(savedUser.id!!)\n assert(foundUser != null)\n assert(foundUser?.name == "إيفان بيتروف")\n }\n\n private fun createDataSource(container: PostgreSQLContainer<*>): DataSource {\n val config = HikariConfig().apply {\n jdbcUrl = container.jdbcUrl\n username = container.username\n password = container.password\n driverClassName = container.driverClassName\n }\n return HikariDataSource(config)\n }\n}\n\nاختبار الخدمات المصغرة مع Kafka و Docker Compose
\n\nللسيناريوهات الأكثر تعقيدًا التي تتطلب عدة خدمات، استخدم Docker Compose عبر Testcontainers:
\n\nimport org.testcontainers.containers.DockerComposeContainer\nimport org.testcontainers.containers.wait.strategy.Wait\nimport java.io.File\n\nclass OrderService