Mockito
Spring Boot অ্যাপ্লিকেশন ডেভেলপ করার সময় টেস্টিং একটি গুরুত্বপূর্ণ অংশ। Mockito হলো একটি জনপ্রিয় Java mocking framework, যা দিয়ে আমরা dependency গুলোকে “mock” করতে পারি, অর্থাৎ আসল অবজেক্ট ছাড়াই unit test চালাতে পারি।
Mockito কী?
Mockito এমন একটি লাইব্রেরি, যা আমাদের কোডের dependency বা external call গুলোকে simulate (mock) করে দেয়।
এতে আমরা মূল লজিক টেস্ট করতে পারি ডাটাবেজ বা নেটওয়ার্কে না গিয়েই। উদাহরণ:
ধরো,
UserServiceক্লাসUserRepositoryএর উপর নির্ভরশীল।
Unit test-এ আমরা চাই না আসল ডাটাবেজে সংযোগ হোক —
বরংUserRepository-কে mock করে নির্দিষ্ট রেসপন্স ফিরিয়ে দিতে পারি।
প্রয়োজনীয় Dependency
pom.xml ফাইলে নিচের dependency যোগ করো:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring Boot এর spring-boot-starter-test প্যাকেজে আগে থেকেই JUnit, Mockito, Hamcrest, AssertJ অন্তর্ভুক্ত থাকে।
উদাহরণ প্রজেক্ট স্ট্রাকচার
src
└── main
└── java/com/example/mockito
├── User.java
├── UserRepository.java
└── UserService.java
└── test
└── java/com/example/mockito
└── UserServiceTest.java
User Entity
public class User {
private Long id;
private String name;
// Constructors, getters, setters
}
Repository Interface
public interface UserRepository {
User findById(Long id);
void save(User user);
}
Service Layer
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public String getUserName(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("User not found!");
}
return user.getName();
}
public void registerUser(User user) {
userRepository.save(user);
}
}
Mockito দিয়ে Unit Test
এখন আমরা UserServiceTest তৈরি করব যেখানে আসল UserRepository এর পরিবর্তে mock ব্যবহার করবো।
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldReturnUserName_WhenUserExists() {
// Arrange
User mockUser = new User();
mockUser.setId(1L);
mockUser.setName("Maruf");
when(userRepository.findById(1L)).thenReturn(mockUser);
// Act
String name = userService.getUserName(1L);
// Assert
assertEquals("Maruf", name);
verify(userRepository, times(1)).findById(1L);
}
@Test
void shouldThrowException_WhenUserNotFound() {
when(userRepository.findById(2L)).thenReturn(null);
assertThrows(RuntimeException.class, () -> userService.getUserName(2L));
verify(userRepository, times(1)).findById(2L);
}
}
এখানে কী ঘটছে
| Annotation / Method | কাজ |
|---|---|
@Mock |
Dependency এর জন্য fake/mock অবজেক্ট তৈরি করে। |
@InjectMocks |
Mock dependency গুলোকে service ক্লাসে inject করে। |
@ExtendWith(MockitoExtension.class) |
Mockito কে JUnit 5 এর সাথে ইন্টিগ্রেট করে। |
when(...).thenReturn(...) |
Mock অবজেক্টের expected behavior সেট করে। |
verify(...) |
কোনো method নির্দিষ্ট সংখ্যক বার কল হয়েছে কিনা যাচাই করে। |
BDD Style Mockito (Behavior Driven Development)
Mockito দিয়ে আমরা BDD স্টাইলেও টেস্ট লিখতে পারি:
import static org.mockito.BDDMockito.*;
@Test
void shouldReturnUserUsingBDD() {
// Given
User user = new User();
user.setId(5L);
user.setName("Rihan");
given(userRepository.findById(5L)).willReturn(user);
// When
String result = userService.getUserName(5L);
// Then
then(userRepository).should(times(1)).findById(5L);
assertEquals("Rihan", result);
}
ArgumentCaptor ব্যবহার
Mockito এর আরেকটি শক্তিশালী ফিচার হলো ArgumentCaptor,
যা দিয়ে আমরা mock method এ পাস করা আর্গুমেন্ট ক্যাপচার করতে পারি।
@Captor
private ArgumentCaptor<User> userCaptor;
@Test
void shouldCaptureUserArgument() {
User user = new User();
user.setName("Niham");
userService.registerUser(user);
verify(userRepository).save(userCaptor.capture());
assertEquals("Niham", userCaptor.getValue().getName());
}
Mockito + Spring Boot Context
যদি তুমি পুরো Spring Context সহ টেস্ট করতে চাও (Integration Test এর কাছাকাছি),
তাহলে ব্যবহার করতে পারো @SpringBootTest ও @MockBean:
@SpringBootTest
class UserServiceSpringBootTest {
@MockBean
private UserRepository userRepository;
@Autowired
private UserService userService;
@Test
void testUserServiceWithMockBean() {
when(userRepository.findById(1L)).thenReturn(new User(1L, "Arni"));
assertEquals("Arni", userService.getUserName(1L));
}
}
@MockBean Spring Context এর মধ্যে bean override করে mock object inject করে দেয়।
Mockito Best Practices
- Unit test সবসময় ছোট ও নির্দিষ্ট behavior টেস্ট করো
- Mock শুধুমাত্র external dependency এর জন্য ব্যবহার করো
- Verify statement এ times(1) বা never() ব্যবহার করো
- Exception test এর জন্য assertThrows ব্যবহার করো
- Integration Test এর জন্য @MockBean ব্যবহার করো, pure Unit Test এর জন্য @Mock