Testcontainers


ইন্টিগ্রেশন টেস্টিং করার সময় আমরা প্রায়ই চাই আমাদের টেস্টগুলো রিয়েল ডাটাবেস, মেসেজ ব্রোকার, বা সার্ভিসের সাথে কাজ করুক।কিন্তু লোকাল বা CI এনভায়রনমেন্টে এসব সেটআপ রাখা জটিল।এই সমস্যার চমৎকার সমাধান হলো  Testcontainers


Testcontainers কী?

Testcontainers হলো একটি Java লাইব্রেরি যা Docker container ব্যবহার করে টেস্ট চলাকালীন সময়ে রিয়েল সার্ভিস স্পিন আপ করে।


এর মাধ্যমে তুমি MySQL, PostgreSQL, MongoDB, Kafka, Redis ইত্যাদি containerized environment-এ টেস্ট চালাতে পারবে। অর্থাৎ, আর ইন-মেমোরি ডাটাবেজ নয় — এবার টেস্ট হবে রিয়েল ডাটাবেজে!


Dependency সেটআপ

pom.xml এ নিচের dependency যোগ করো:

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <scope>test</scope>
</dependency>

<!-- উদাহরণস্বরূপ PostgreSQL এর জন্য -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
</dependency>


একটি উদাহরণ প্রজেক্ট

ধরা যাক আমাদের একটি Spring Boot অ্যাপ আছে যেখানে User entity PostgreSQL ডাটাবেজে সংরক্ষণ হয়।

Entity

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // constructor, getters, setters
}


Repository

public interface UserRepository extends JpaRepository<User, Long> {
}


Testcontainers দিয়ে Integration Test

@SpringBootTest
@Testcontainers
public class UserRepositoryIntegrationTest {

    // PostgreSQL container
    @Container
    static PostgreSQLContainer<?> postgresDB = new PostgreSQLContainer<>("postgres:16")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @Autowired
    private UserRepository userRepository;

    @DynamicPropertySource
    static void configure(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgresDB::getJdbcUrl);
        registry.add("spring.datasource.username", postgresDB::getUsername);
        registry.add("spring.datasource.password", postgresDB::getPassword);
    }

    @Test
    void testUserSaveAndFind() {
        User user = new User();
        user.setName("Maruf");
        userRepository.save(user);

        List<User> users = userRepository.findAll();
        assertEquals(1, users.size());
        assertEquals("Maruf", users.get(0).getName());
    }
}


এখানে কী ঘটছে

Annotation / Class কাজ
@Testcontainers Testcontainers ফিচার সক্রিয় করে।
@Container Docker container লাইফসাইকেল ম্যানেজ করে (start/stop)।
PostgreSQLContainer PostgreSQL এর docker image চালায়।
@DynamicPropertySource Spring Context-এ runtime property inject করে।
@SpringBootTest পুরো Spring Context লোড করে Integration Test চালায়।


Docker ইন্সটল থাকা জরুরি

Testcontainers মূলত Docker ব্যবহার করে runtime এ container চালায়।
তাই সিস্টেমে Docker Desktop / Docker Engine ইনস্টল থাকা আবশ্যক।

Tip: Docker চালু না থাকলে টেস্ট ব্যর্থ হবে “Connection refused” এরর সহ।


Commonly Used Containers

Service Container Class Example Image
PostgreSQL PostgreSQLContainer postgres:16
MySQL MySQLContainer mysql:8.0
MongoDB MongoDBContainer mongo:7
Redis GenericContainer redis:latest
Kafka KafkaContainer confluentinc/cp-kafka:latest

উদাহরণস্বরূপ, Kafka টেস্ট করতে পারো এভাবে:

@Container
static KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));


Testcontainers এর সুবিধা

- রিয়েল সার্ভিসে টেস্ট করা যায় (production-like environment)
- আলাদা configuration বা script লাগে না
- টেস্ট শেষে container স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়
- CI/CD পাইপলাইনে সহজে ইন্টিগ্রেট করা যায়


Advanced Setup – Compose ফাইল সহ

তুমি চাইলে Docker Compose ফাইল ব্যবহার করে একাধিক সার্ভিস একসাথে চালাতে পারো:

@Container
static DockerComposeContainer<?> environment =
    new DockerComposeContainer<>(new File("src/test/resources/docker-compose.yml"))
        .withExposedService("postgres", 5432)
        .withExposedService("redis", 6379);


Testcontainers + Flyway

যদি তুমি Database Migration Tool (যেমন Flyway বা Liquibase) ব্যবহার করো,
Testcontainers context load করার সময় স্বয়ংক্রিয়ভাবে migration চালিয়ে নেয়।

spring:
  flyway:
    enabled: true