Integration testing


Spring Boot অ্যাপ্লিকেশন ডেভেলপ করার সময় আমরা সাধারণত দুটি ধরণের টেস্ট লিখি — Unit Test এবং Integration Test

Unit Test আলাদা আলাদা ক্লাস বা মেথড যাচাই করে, কিন্তু Integration Test পুরো সিস্টেমের বিভিন্ন অংশ একসাথে ঠিকভাবে কাজ করছে কিনা তা যাচাই করে।


Integration Test কী?

Integration Test হলো এমন একটি টেস্ট যেখানে Spring ApplicationContext পুরোপুরি লোড হয়,
এবং Repository, Service, Controller ইত্যাদি একসাথে কাজ করে কিনা তা যাচাই করা হয়।

উদাহরণ:

“UserController → UserService → UserRepository” চেইন একসাথে সঠিকভাবে কাজ করছে কিনা,
সেটি যাচাই করতে Integration Test ব্যবহার করা হয়।


প্রয়োজনীয় Dependency

Spring Boot এ Integration Testing সহজ করতে নিচের dependency গুলো ব্যবহার হয়:

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

এখানে spring-boot-starter-test প্যাকেজের মধ্যে JUnit, Mockito, AssertJ, Hamcrest, Spring Test Context ইত্যাদি সব কিছুই আগে থেকেই অন্তর্ভুক্ত থাকে।


একটি সাধারণ Integration Test এর উদাহরণ

ধরা যাক আমাদের একটি UserController আছে, যা ডাটাবেস থেকে ইউজার লিস্ট রিটার্ন করে।

Entity

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


Repository

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


Service

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}


Controller

@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getUsers() {
        return userService.getAllUsers();
    }
}


Integration Test লিখি

@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private UserRepository userRepository;

    @BeforeEach
    void setUp() {
        userRepository.deleteAll();
        userRepository.save(new User(null, "Maruf"));
        userRepository.save(new User(null, "Rihan"));
    }

    @Test
    void shouldReturnAllUsers() throws Exception {
        mockMvc.perform(get("/api/users"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.length()").value(2))
                .andExpect(jsonPath("$[0].name").value("Maruf"));
    }
}


এখানে কী হচ্ছে

Annotation কাজ
@SpringBootTest পুরো Spring Context লোড করে (Controller, Service, Repository সব সহ)।
@AutoConfigureMockMvc MockMvc কনফিগার করে যাতে আমরা HTTP রিকোয়েস্ট simulate করতে পারি।
@BeforeEach প্রতিটি টেস্টের আগে ডাটাবেজ initialize করে।
mockMvc.perform(...) API কল simulate করে যেমন /api/users


Database নিয়ে Integration Test

Integration Test সাধারণত in-memory ডাটাবেজ যেমন H2 ব্যবহার করে।

# src/test/resources/application.yml
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driverClassName: org.h2.Driver
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create-drop

এতে করে টেস্টের সময় একটা অস্থায়ী ডাটাবেজ তৈরি হয় এবং প্রতিটি টেস্ট শেষে ডিলিট হয়ে যায়।


REST API Integration Test (JSON সহ)

@Test
void shouldCreateNewUser() throws Exception {
    String newUser = "{\"name\": \"Niham\"}";

    mockMvc.perform(post("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content(newUser))
            .andExpect(status().isOk());

    assertEquals(3, userRepository.count());
}


Transactional Test

যদি প্রতিটি টেস্ট শেষে ডাটাবেজে করা পরিবর্তন rollback করতে চাও,
তাহলে @Transactional annotation ব্যবহার করো:

@SpringBootTest
@Transactional
public class UserRepositoryTest {
    @Autowired
    private UserRepository repo;

    @Test
    void testSaveUser() {
        repo.save(new User(null, "TestUser"));
        assertEquals(1, repo.count());
    }
}

এখানে প্রতিটি টেস্ট শেষে Spring স্বয়ংক্রিয়ভাবে transaction rollback করবে।


Test Slicing (Controller / Repository আলাদা করে টেস্ট করা)

Spring Boot কিছু smart test slice annotations দিয়েছে:

Annotation কাজ
@WebMvcTest শুধু Controller layer টেস্ট করে (Service/Repository লোড হয় না)।
@DataJpaTest শুধুমাত্র Repository layer টেস্ট করে (H2 database সহ)।
@JsonTest JSON serialization/deserialization টেস্ট করে।


উদাহরণ:

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void saveAndFindUser() {
        userRepository.save(new User(null, "Arni"));
        Optional<User> user = userRepository.findById(1L);
        assertTrue(user.isPresent());
    }
}