JUnit 5
Spring Boot অ্যাপ্লিকেশন তৈরি করার সময় Unit Testing সবচেয়ে গুরুত্বপূর্ণ বিষয়গুলোর একটি Java ecosystem-এ সবচেয়ে জনপ্রিয় টেস্টিং ফ্রেমওয়ার্ক হলো JUnit। এবং Spring Boot এখন JUnit 5 (Jupiter) এর সাথে সম্পূর্ণভাবে ইন্টিগ্রেটেড।
কেন JUnit 5?
JUnit 5, JUnit 4 এর তুলনায় অনেক বেশি আধুনিক, modular এবং flexible। এতে তিনটি মূল অংশ রয়েছে:
| Module | কাজ |
|---|---|
| JUnit Platform | Test engine চালানোর বেস ফ্রেমওয়ার্ক |
| JUnit Jupiter | নতুন annotations এবং API |
| JUnit Vintage | পুরনো JUnit 3/4 টেস্ট চালানোর জন্য |
Dependency সেটআপ
pom.xml ফাইলে নিচের dependency যোগ করলেই JUnit 5 চলে যাবে (Spring Boot Starter Test এর মাধ্যমেই):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring Boot 2.2+ থেকে JUnit 5 ডিফল্টভাবে থাকে, তাই আলাদা কিছু করার প্রয়োজন নেই।
একটি সাধারণ Unit Test উদাহরণ
ধরা যাক আমাদের একটি সার্ভিস ক্লাস আছে:
@Service
public class CalculatorService {
public int add(int a, int b) {
return a + b;
}
public int divide(int a, int b) {
return a / b;
}
}
এখন আমরা এর জন্য টেস্ট লিখব:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorServiceTest {
private final CalculatorService service = new CalculatorService();
@Test
void testAddition() {
assertEquals(5, service.add(2, 3));
}
@Test
void testDivision() {
assertThrows(ArithmeticException.class, () -> service.divide(5, 0));
}
}
JUnit 5 Annotations
| Annotation | কাজ |
|---|---|
@Test |
টেস্ট মেথড নির্দেশ করে |
@BeforeEach |
প্রতিটি টেস্টের আগে রান হয় |
@AfterEach |
প্রতিটি টেস্টের পর রান হয় |
@BeforeAll |
সব টেস্টের আগে একবার রান হয় (static হতে হবে) |
@AfterAll |
সব টেস্টের পরে একবার রান হয় (static হতে হবে) |
@DisplayName |
টেস্টের জন্য কাস্টম নাম সেট করে |
@Disabled |
কোনো টেস্ট skip করতে ব্যবহার হয় |
উদাহরণ:
@BeforeAll
static void setup() {
System.out.println("Starting tests...");
}
@BeforeEach
void init() {
System.out.println("Init before each test");
}
@AfterEach
void tearDown() {
System.out.println("Cleaning up...");
}
Assertions API
JUnit 5 এ org.junit.jupiter.api.Assertions প্যাকেজে বেশ কিছু শক্তিশালী assertion method আছে:
| Assertion | কাজ |
|---|---|
assertEquals(expected, actual) |
দুটি মান সমান কিনা যাচাই করে |
assertNotNull(object) |
অবজেক্ট null নয় কিনা যাচাই করে |
assertTrue(condition) |
শর্ত সত্য কিনা যাচাই করে |
assertThrows(Exception.class, ...) |
Exception ছোঁড়া হয়েছে কিনা চেক করে |
assertAll(...) |
একাধিক assertion একসাথে রান করে |
উদাহরণ:
@Test
void testMultipleAssertions() {
assertAll(
() -> assertEquals(10, 5 + 5),
() -> assertTrue("Hello".startsWith("H")),
() -> assertNotNull(new Object())
);
}
Parameterized Tests
JUnit 5 এর সবচেয়ে আকর্ষণীয় ফিচার হলো @ParameterizedTest, যার মাধ্যমে আমরা একই টেস্টে একাধিক ইনপুট দিয়ে ফলাফল যাচাই করতে পারি।
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class ParameterizedExampleTest {
@ParameterizedTest
@ValueSource(strings = {"Spring", "JUnit", "Mockito"})
void testStringNotEmpty(String word) {
assertFalse(word.isEmpty());
}
}
এছাড়াও আমরা @CsvSource, @EnumSource, @MethodSource ইত্যাদি ব্যবহার করতে পারি।
Spring Boot Integration সহ JUnit 5
Spring Boot অ্যাপ্লিকেশন context লোড করে টেস্ট চালাতে চাইলে ব্যবহার করো @SpringBootTest:
@SpringBootTest
class ApplicationIntegrationTest {
@Autowired
private CalculatorService service;
@Test
void testServiceBean() {
assertNotNull(service);
assertEquals(7, service.add(3, 4));
}
}
👉 এখানে Spring Boot পুরো context লোড করে এবং bean injection সম্পন্ন করে।
Mocking সহ JUnit + Mockito
Spring Boot টেস্টে mock object ব্যবহার করতে চাইলে @Mock ও @InjectMocks ব্যবহার করো:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository repo;
@InjectMocks
private UserService service;
@Test
void testGetUser() {
when(repo.findById(1L)).thenReturn(Optional.of(new User(1L, "Maruf")));
User user = service.getUserById(1L);
assertEquals("Maruf", user.getName());
}
}
@DataJpaTest — Repository Testing
Spring Data JPA repository টেস্ট করার জন্য সবচেয়ে জনপ্রিয় annotation হলো @DataJpaTest:
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void testSaveUser() {
User user = new User(null, "Rihan");
User saved = userRepository.save(user);
assertNotNull(saved.getId());
}
}
এটি ইন-মেমোরি ডাটাবেজ (যেমন H2) ব্যবহার করে এবং শুধুমাত্র repository সম্পর্কিত bean লোড করে।
Nested Tests
JUnit 5 এ nested test class ব্যবহার করা যায়, যা টেস্ট সংগঠিত রাখতে সহায়তা করে।
class MathTest {
@Nested
class AddTests {
@Test
void addTwoNumbers() {
assertEquals(8, 3 + 5);
}
}
@Nested
class SubtractTests {
@Test
void subtractNumbers() {
assertEquals(2, 5 - 3);
}
}
}
Tips & Best Practices
- টেস্ট ক্লাসের নাম শেষে “Test” রাখো (যেমন UserServiceTest)
- প্রতিটি ইউনিট আলাদা টেস্টে ভাঙো
- টেস্ট নাম অর্থবোধক রাখো (shouldReturnUserWhenIdIsValid())
- Mock ব্যবহার করো external dependency এর জন্য
- CI/CD তে mvn test বা gradle test চালাও