Argument Matchers হল EasyMock এর একটি শক্তিশালী বৈশিষ্ট্য যা আপনাকে মক অবজেক্টের মেথডের জন্য আর্গুমেন্টগুলিকে নমনীয়ভাবে এবং জন্য মান ছাড়া সেট করার সুযোগ দেয়। এটি ব্যবহার করে আপনি specific values এর পরিবর্তে general patterns অথবা wildcard হিসেবে আর্গুমেন্ট নির্ধারণ করতে পারেন। এটি বিশেষভাবে উপকারী যখন আপনি জানেন না কী আর্গুমেন্ট আসবে, তবে কিছু সাধারণ শর্তে সেটি মেলানোর জন্য চান।
যেমন, আপনি যদি চান যে কোন একটি মেথড anyInt(), anyString(), anyObject() এর মতো প্যাটার্ন অনুযায়ী আর্গুমেন্ট গ্রহণ করুক, তবে EasyMock এর Argument Matchers এর সাহায্যে আপনি তা সহজেই করতে পারেন।
Argument Matchers কী?
Argument Matchers EasyMock এ ব্যবহৃত হয় যখন আপনি চান মক অবজেক্টের মেথডটি নির্দিষ্ট আর্গুমেন্টের জন্য কল না হয়ে কোনো আর্গুমেন্ট নিয়েও কাজ করুক। এটি মেথডের আর্গুমেন্টের প্রতি একটি সাধারণ শর্ত বা ম্যাপিং নির্ধারণ করতে দেয়।
Common Argument Matchers
- anyInt(): যেকোনো int আর্গুমেন্ট গ্রহণ করে।
- anyString(): যেকোনো String আর্গুমেন্ট গ্রহণ করে।
- anyObject(): যেকোনো Object আর্গুমেন্ট গ্রহণ করে।
- eq(): সুনির্দিষ্ট মানের জন্য আর্গুমেন্ট মেলে (যেমন,
eq(5)মানে,5আর্গুমেন্ট থাকা উচিত)। - isA(): একটি নির্দিষ্ট টাইপের আর্গুমেন্ট মেলে (যেমন,
isA(String.class)মানে,Stringটাইপের আর্গুমেন্ট হওয়া উচিত)। - notNull():
nullছাড়া যেকোনো মানের জন্য মেলে। - isNull(): শুধুমাত্র
nullমানের জন্য মেলে।
EasyMock এ Argument Matchers ব্যবহার করার উদাহরণ
ধরা যাক, আমাদের একটি Calculator ক্লাস রয়েছে এবং আমরা add(), multiply() মেথডগুলোর জন্য মক তৈরি করতে চাই। আমরা Argument Matchers ব্যবহার করে মেথডের আর্গুমেন্টগুলির জন্য সাধারণ শর্ত সেট করব।
Step 1: Calculator ক্লাস
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
return a * b;
}
}
Step 2: Testing with EasyMock (Argument Matchers)
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CalculatorTest {
private Calculator calculatorMock;
@Before
public void setUp() {
// Create a mock object of Calculator
calculatorMock = EasyMock.createMock(Calculator.class);
}
@Test
public void testAddWithArgumentMatchers() {
// Expectation: anyInt() is used as argument matcher
EasyMock.expect(calculatorMock.add(EasyMock.anyInt(), EasyMock.anyInt())).andReturn(10).anyTimes();
// Activate the mock
EasyMock.replay(calculatorMock);
// Running the test
int result = calculatorMock.add(3, 7); // anyInt() will match any int
assertEquals(10, result); // Expected result is 10
// Verify mock behavior
EasyMock.verify(calculatorMock);
}
@Test
public void testMultiplyWithArgumentMatchers() {
// Expectation: multiply method with any argument
EasyMock.expect(calculatorMock.multiply(EasyMock.anyInt(), EasyMock.anyInt())).andReturn(20).anyTimes();
// Activate the mock
EasyMock.replay(calculatorMock);
// Running the test
int result = calculatorMock.multiply(4, 5); // anyInt() will match any int
assertEquals(20, result); // Expected result is 20
// Verify mock behavior
EasyMock.verify(calculatorMock);
}
@Test
public void testAddWithSpecificArgumentMatcher() {
// Expectation: eq() is used to match exact arguments
EasyMock.expect(calculatorMock.add(EasyMock.eq(5), EasyMock.eq(5))).andReturn(10);
// Activate the mock
EasyMock.replay(calculatorMock);
// Running the test
int result = calculatorMock.add(5, 5); // Only this call will match (eq(5), eq(5))
assertEquals(10, result); // Expected result is 10
// Verify mock behavior
EasyMock.verify(calculatorMock);
}
}
ব্যাখ্যা:
- anyInt():
- এই matcher ব্যবহার করা হয়েছে, যাতে
add()এবংmultiply()মেথডের যেকোনো int আর্গুমেন্ট মেলা যায়। এটি নিশ্চিত করে যে, আমরা ঠিক কী ভ্যালু পাঠাচ্ছি সেটা বিবেচনা না করে, যে কোনintইনপুটে মক অবজেক্ট নির্দিষ্ট রিটার্ন ভ্যালু দেবে। EasyMock.expect(calculatorMock.add(EasyMock.anyInt(), EasyMock.anyInt())).andReturn(10);এখানেanyInt()ব্যবহার করা হয়েছে।
- এই matcher ব্যবহার করা হয়েছে, যাতে
- eq():
eq()ব্যবহার করা হয়েছে যখন আপনি specific value চাচ্ছেন। এই ক্ষেত্রে,calculatorMock.add(EasyMock.eq(5), EasyMock.eq(5))দ্বারা আমরা নির্দিষ্টভাবে চাচ্ছি যে,add()মেথডটি 5 এবং 5 ইনপুটে কল হবে।eq()শুধুমাত্র সুনির্দিষ্ট মানের জন্য কাজ করে।
Argument Matchers এর অন্যান্য ব্যবহার
isA(): একটি নির্দিষ্ট টাইপের আর্গুমেন্ট মেলানোর জন্য।
EasyMock.expect(calculatorMock.add(EasyMock.isA(Integer.class), EasyMock.isA(Integer.class))) .andReturn(10);notNull():
nullছাড়া যেকোনো মানের জন্য মেলে।EasyMock.expect(calculatorMock.add(EasyMock.notNull(), EasyMock.notNull())) .andReturn(10);isNull(): শুধুমাত্র
nullমানের জন্য মেলে।EasyMock.expect(calculatorMock.add(EasyMock.isNull(), EasyMock.isNull())) .andReturn(10);anyObject(): যেকোনো অবজেক্ট মেলানোর জন্য।
EasyMock.expect(calculatorMock.add(EasyMock.anyObject(), EasyMock.anyObject())) .andReturn(10);
Argument Matchers এর সুবিধা:
- নমনীয়তা: আর্গুমেন্টগুলির জন্য শক্তিশালী ও নমনীয় ম্যাচিং সমর্থন প্রদান করে।
- ফ্লেক্সিবিলিটি: আপনি মেথড কলের জন্য specific value ছাড়াও wildcards ব্যবহার করতে পারেন, যা টেস্টিংকে আরও সহজ ও দ্রুত করে তোলে।
- Test Maintenance: আপনি সহজে generalized tests তৈরি করতে পারেন যা নির্দিষ্ট মানের প্রতি নির্ভরশীল নয়।
সারাংশ
Argument Matchers EasyMock এর একটি শক্তিশালী বৈশিষ্ট্য যা আপনাকে মক অবজেক্টের আর্গুমেন্টগুলিকে নমনীয়ভাবে এবং সহজে মেলানোর সুযোগ দেয়। anyInt(), eq(), isA(), notNull(), anyObject() ইত্যাদি matcher ব্যবহার করে আপনি মেথড কলের আর্গুমেন্ট নির্ধারণ করতে পারেন। এটি টেস্টিংকে আরও সহজ এবং বেশি generalized করতে সহায়তা করে, এবং আপনার unit tests কে আরও নমনীয় ও নির্ভরযোগ্য করে তোলে।
Argument Matchers হল EasyMock এর একটি শক্তিশালী বৈশিষ্ট্য যা মক অবজেক্টের জন্য ইনপুট আর্গুমেন্টগুলির মূল্য নির্ধারণ করার সময় নমনীয়তা (flexibility) প্রদান করে। যখন আমরা একটি মক অবজেক্টের জন্য expect() মেথড ব্যবহার করে আর্গুমেন্টের সাথে একটি মেথড কল নির্ধারণ করি, তখন কখনও কখনও আমরা ঠিক নির্দিষ্ট মান এর পরিবর্তে যেকোনো মান বা কিছু শর্ত মেলে এমন আর্গুমেন্টগুলির জন্য সেই মেথডের আচরণ ডিফাইন করতে চাই। এই কাজটি Argument Matchers এর মাধ্যমে করা যায়।
Argument Matchers আমাদেরকে মক অবজেক্টের জন্য আর্গুমেন্টগুলো নির্দিষ্ট করার সময় নমনীয়তা প্রদান করে, যেমন:
- কোনো নির্দিষ্ট মানের জন্য নয়, বরং একটি নির্দিষ্ট ধরণের আর্গুমেন্টের জন্য আচরণ নির্ধারণ করা।
- একাধিক মানের পরিবর্তে wildcard আর্গুমেন্ট ব্যবহার করা।
- আর্গুমেন্টের কোনো শর্ত বা অবস্থা (condition) মেলে এমন কেসগুলি চেক করা।
Argument Matchers এর কাজ
Argument Matchers EasyMock-এ যেকোনো আর্গুমেন্টের জন্য শর্ত এবং নমনীয়তা নির্ধারণ করতে ব্যবহৃত হয়, যেমন:
- any(): যেকোনো মানের জন্য মেলে।
- eq(): নির্দিষ্ট মানের জন্য মেলে।
- isA(): একটি নির্দিষ্ট ধরনের অবজেক্টের জন্য মেলে।
- gt(), lt(): বড় বা ছোট মানের জন্য মেলে।
- notNull(): আর্গুমেন্টটি নাল নয় এমন মানের জন্য মেলে।
- same(): একই অবজেক্টের জন্য মেলে (references).
Commonly Used Argument Matchers
- any(): এটি যেকোনো আর্গুমেন্টের জন্য মেলে।
- উদাহরণ:
anyInt()- যেকোনো পূর্ণসংখ্যার জন্য।
- উদাহরণ:
- eq(): এটি নির্দিষ্ট আর্গুমেন্টের জন্য মেলে।
- উদাহরণ:
eq(5)- শুধুমাত্র মান ৫ এর জন্য।
- উদাহরণ:
- isA(): এটি একটি নির্দিষ্ট ক্লাসের অবজেক্টের জন্য মেলে।
- উদাহরণ:
isA(String.class)- যেকোনো String অবজেক্টের জন্য।
- উদাহরণ:
- gt(), lt(): বড় বা ছোট আর্গুমেন্টের জন্য মেলে।
- উদাহরণ:
gt(5)- ৫ এর চেয়ে বড় মানের জন্য।
- উদাহরণ:
- notNull(): এটি নিশ্চিত করে যে আর্গুমেন্টটি
nullনয়।- উদাহরণ:
notNull()- যেকোনো non-null আর্গুমেন্টের জন্য।
- উদাহরণ:
- same(): এটি একই অবজেক্টের জন্য মেলে (object reference comparison)।
- উদাহরণ:
same(foo)- যেখানেfooএকটি অবজেক্ট, এটি শুধুমাত্র ঐ অবজেক্টটির জন্য কাজ করবে।
- উদাহরণ:
EasyMock Example: Argument Matchers
এখন আসুন, একটি EasyMock উদাহরণ দেখি যেখানে আমরা Argument Matchers ব্যবহার করব। এখানে আমরা একটি Calculator ইন্টারফেসের মক অবজেক্ট তৈরি করব এবং বিভিন্ন আর্গুমেন্ট মেচারের মাধ্যমে আর্গুমেন্টে বিভিন্ন শর্ত মেনে টেস্ট করব।
1. Calculator Interface:
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
}
2. EasyMock Example with Argument Matchers:
import static org.easymock.EasyMock.*;
public class EasyMockArgumentMatchersExample {
public static void main(String[] args) {
// Create a mock object of the Calculator interface
Calculator calculatorMock = createMock(Calculator.class);
// Set up expectations using Argument Matchers
expect(calculatorMock.add(anyInt(), eq(5))).andReturn(10); // anyInt() for first arg, eq(5) for second
expect(calculatorMock.subtract(gt(10), lt(20))).andReturn(5); // gt(10) and lt(20) for range check
// Activate the mock
replay(calculatorMock);
// Test the methods with mock behavior
System.out.println("Addition result: " + calculatorMock.add(3, 5)); // Should return 10
System.out.println("Subtraction result: " + calculatorMock.subtract(15, 5)); // Should return 5
// Verify that the expected methods were called
verify(calculatorMock);
}
}
Output:
Addition result: 10
Subtraction result: 5
Explanation:
anyInt(): এখানেanyInt()ব্যবহার করা হয়েছে, যার মানে হল প্রথম আর্গুমেন্ট হিসেবে যেকোনো পূর্ণসংখ্যা গ্রহণ করা হবে।eq(5): এই matcher দিয়ে নিশ্চিত করা হয়েছে যে দ্বিতীয় আর্গুমেন্টে 5 হতে হবে।gt(10)এবংlt(20): এখানে gt(10) (১০ এর চেয়ে বড়) এবং lt(20) (২০ এর চেয়ে ছোট) শর্তে subtract() মেথডটি পরীক্ষা করা হয়েছে।
EasyMock Argument Matchers এর গুরুত্বপূর্ণ ব্যবহার
- Flexible Method Calls: Argument matchers ব্যবহার করে আমরা কোনো নির্দিষ্ট মান বা শর্তের জন্য মক অবজেক্টের আচরণ ডিফাইন করতে পারি।
- Testing Complex Logic: যখন কোনো মেথডে নানা ধরনের ইনপুট থাকে, তখন argument matchers এর মাধ্যমে সহজেই তাদের যাচাই করা যায়।
- Simplified Testing: যদি একাধিক আর্গুমেন্টের মধ্যে অনেকগুলো ভিন্ন ভিন্ন শর্ত থাকে, তবে EasyMock এর argument matchers এর সাহায্যে পরীক্ষাটি আরও সহজ ও নমনীয় করা যায়।
সারাংশ
Argument Matchers হল EasyMock এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা মক অবজেক্টের জন্য আর্গুমেন্টের ম্যাচিংকে নমনীয় এবং শক্তিশালী করে তোলে। any(), eq(), gt(), isA(), notNull() ইত্যাদি মেচারদের মাধ্যমে আমরা মক অবজেক্টের জন্য বিভিন্ন আর্গুমেন্টের জন্য behavior ডিফাইন করতে পারি এবং টেস্টিংয়ের নমনীয়তা বাড়াতে পারি। এটি কোড টেস্টিংকে আরও সঠিক এবং কার্যকরী করে তোলে, বিশেষত যখন মেথডে ভিন্ন ভিন্ন আর্গুমেন্ট বা শর্ত থাকে।
EasyMock একটি জনপ্রিয় mocking framework যা ইউনিট টেস্টিং এবং ডিপেন্ডেন্সি ইনজেকশন পরীক্ষার জন্য ব্যবহৃত হয়। এর মাধ্যমে আপনি নির্দিষ্ট method calls এর জন্য arguments মক করতে পারেন, যাতে সঠিক ইনপুট দিয়ে সিস্টেমের আচরণ পরীক্ষা করা যায়। eq(), anyObject(), এবং anyInt() হল EasyMock এর কিছু গুরুত্বপূর্ণ মেথড যা টেস্টের সময় ব্যবহারকারীর আর্গুমেন্ট চেক করতে সাহায্য করে।
1. eq() Method
eq() মেথড ব্যবহার করা হয় যখন আপনি কোনও নির্দিষ্ট মানের জন্য মক অবজেক্টে প্রত্যাশা নির্ধারণ করতে চান। এটি exact match এর জন্য ব্যবহৃত হয়। যদি আপনি কোনো মেথড কলের জন্য নির্দিষ্ট ইনপুট দিতে চান, তবে eq() ব্যবহার করতে পারেন।
eq() এর উদাহরণ:
import static org.easymock.EasyMock.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class EasyMockTest {
public interface UserRepository {
User findUserById(int id);
}
@Test
public void testFindUserByIdWithEq() {
// Create a mock UserRepository
UserRepository mockUserRepository = createMock(UserRepository.class);
// Set the expectation for method call with exact match
expect(mockUserRepository.findUserById(eq(1))).andReturn(new User(1, "John"));
// Activate the mock object
replay(mockUserRepository);
// Create the service and use mock
UserService userService = new UserService(mockUserRepository);
String userName = userService.getUserName(1);
assertEquals("John", userName);
// Verify the behavior of the mock
verify(mockUserRepository);
}
}
ব্যাখ্যা:
eq(1)ব্যবহার করা হয়েছেfindUserById(1)মেথডের জন্য যাতে এটি exactly 1 এর জন্য সঠিক রিটার্ন মান প্রদান করে।replay()মেথডের মাধ্যমে মক অবজেক্টের আচরণ বাস্তবায়ন করা হয়েছে।verify()মেথডের মাধ্যমে নিশ্চিত করা হয়েছে যে মক অবজেক্টটি প্রত্যাশিতভাবে কল হয়েছে।
2. anyObject() Method
anyObject() মেথড ব্যবহার করা হয় যখন আপনি কোনো সাধারণ Object টাইপের প্যারামিটার চাইছেন, কিন্তু তার কোনো নির্দিষ্ট মান প্রয়োজন নেই। এই মেথডটি সব ধরনের অবজেক্টের জন্য ব্যবহার করা যেতে পারে।
anyObject() এর উদাহরণ:
import static org.easymock.EasyMock.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class EasyMockTest {
public interface UserRepository {
User saveUser(User user);
}
@Test
public void testSaveUserWithAnyObject() {
// Create a mock UserRepository
UserRepository mockUserRepository = createMock(UserRepository.class);
// Set the expectation for method call with any object
expect(mockUserRepository.saveUser(anyObject())).andReturn(new User(1, "John"));
// Activate the mock object
replay(mockUserRepository);
// Create the service and use mock
UserService userService = new UserService(mockUserRepository);
User user = new User(1, "John");
String result = userService.saveUser(user);
assertEquals("User saved", result);
// Verify the behavior of the mock
verify(mockUserRepository);
}
}
ব্যাখ্যা:
anyObject()ব্যবহার করা হয়েছেsaveUser()মেথডের জন্য, যেহেতু এখানে ইউজারের অবজেক্টের প্রকৃত মান পরীক্ষা করার কোনো প্রয়োজন নেই।- এইভাবে, কোন নির্দিষ্ট মান বা অবজেক্টের চেক না করেও মক অবজেক্টে সাধারণত কোনো আর্গুমেন্ট পাস করা যায়।
3. anyInt() Method
anyInt() মেথড ব্যবহার করা হয় যখন আপনি কোনো integer প্যারামিটার চান, কিন্তু তার নির্দিষ্ট মানের প্রয়োজন নেই। এটি যে কোন ইন্টিজার মানকে গ্রহণ করবে।
anyInt() এর উদাহরণ:
import static org.easymock.EasyMock.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class EasyMockTest {
public interface UserRepository {
User findUserById(int id);
}
@Test
public void testFindUserByIdWithAnyInt() {
// Create a mock UserRepository
UserRepository mockUserRepository = createMock(UserRepository.class);
// Set the expectation for method call with any integer
expect(mockUserRepository.findUserById(anyInt())).andReturn(new User(1, "John"));
// Activate the mock object
replay(mockUserRepository);
// Create the service and use mock
UserService userService = new UserService(mockUserRepository);
String userName = userService.getUserName(123);
assertEquals("John", userName);
// Verify the behavior of the mock
verify(mockUserRepository);
}
}
ব্যাখ্যা:
anyInt()ব্যবহার করা হয়েছেfindUserById()মেথডের জন্য, যাতে কোনো নির্দিষ্ট ইনপুটের প্রয়োজন না হয় এবং integer টাইপের যে কোন প্যারামিটার গ্রহণ করা যায়।- এটি ব্যবহারকারীর ইনপুটের জন্য কোনো নির্দিষ্ট সংখ্যা প্রয়োজন ছাড়াই মক অবজেক্টের আচরণ নির্ধারণ করতে সাহায্য করে।
eq(), anyObject(), এবং anyInt() এর সুবিধা:
- eq():
- এটি ব্যবহার করে নির্দিষ্ট আর্গুমেন্টের জন্য স্পষ্টভাবে প্রত্যাশিত রিটার্ন ভ্যালু সেট করা যায়। যেমন: শুধুমাত্র
1এর জন্যfindById()মেথড কল করা হবে।
- এটি ব্যবহার করে নির্দিষ্ট আর্গুমেন্টের জন্য স্পষ্টভাবে প্রত্যাশিত রিটার্ন ভ্যালু সেট করা যায়। যেমন: শুধুমাত্র
- anyObject():
- এটি সব ধরনের অবজেক্টের জন্য ব্যবহার করা যায় এবং এটি কোনো নির্দিষ্ট মানের প্রয়োজন ছাড়াই আর্গুমেন্ট গ্রহণ করতে পারে। এটি সাধারণত যখন আপনি জানেন না বা কোনো নির্দিষ্ট মানের জন্য পরীক্ষা করতে চান না তখন ব্যবহৃত হয়।
- anyInt():
- এটি integer টাইপের আর্গুমেন্টের জন্য ব্যবহৃত হয় এবং আপনি কোন নির্দিষ্ট সংখ্যা চেক করতে না চাইলেও এটি যেকোনো ইন্টিজার ইনপুট গ্রহণ করবে। এটি সাধারণত এমন পরিস্থিতিতে ব্যবহৃত হয় যখন প্যারামিটারটি কোনো নির্দিষ্ট মানের উপর নির্ভরশীল নয়।
সারাংশ
EasyMock এর eq(), anyObject(), এবং anyInt() মেথডগুলি ইউনিট টেস্টিং করার সময় খুবই গুরুত্বপূর্ণ, কারণ এগুলি আপনাকে মক অবজেক্টের ইনপুট আর্গুমেন্টের জন্য অত্যন্ত নমনীয়তা প্রদান করে। এগুলি:
- eq() নির্দিষ্ট মানের জন্য ব্যবহৃত হয়,
- anyObject() কোনো ধরনের অবজেক্টের জন্য ব্যবহৃত হয়,
- anyInt() ইন্টিজার টাইপের আর্গুমেন্টের জন্য ব্যবহৃত হয়।
এই মেথডগুলির মাধ্যমে আপনি আরও নিয়ন্ত্রণ সহকারে এবং পরিষ্কারভাবে টেস্টিং করতে পারবেন, যেখানে প্রতিটি ইনপুটের উপর পরীক্ষা নির্ধারণ করা যায়।
EasyMock একটি শক্তিশালী মকিং ফ্রেমওয়ার্ক, যা আপনি mock objects এবং stubbing করতে ব্যবহার করতে পারেন। কখনও কখনও আপনাকে টেস্টিংয়ের সময় বিশেষ ধরনের আর্গুমেন্টের জন্য মকিং করতে হতে পারে, যা EasyMock এর ডিফল্ট আর্গুমেন্ট ম্যাচার দ্বারা ক্যাপচার করা সম্ভব নয়। এই ক্ষেত্রে, আপনি Custom Argument Matcher তৈরি করতে পারেন।
Custom Argument Matcher হল এমন একটি ক্লাস যা ArgumentMatcher ইন্টারফেসকে বাস্তবায়িত করে এবং কাস্টম যুক্তি যাচাই করতে ব্যবহার করা হয়। এটি আপনাকে মক অবজেক্টে নির্দিষ্ট আর্গুমেন্টের জন্য কাস্টম শর্তাদি প্রয়োগ করতে দেয়।
ArgumentMatcher Interface:
EasyMock তে ArgumentMatcher ইন্টারফেস ব্যবহার করা হয়। এই ইন্টারফেসের মাধ্যমে আপনি কাস্টম ম্যাচিং লজিক তৈরি করতে পারেন। এর প্রধান মেথডগুলো হল:
matches(Object arg): এই মেথডটি আর্গুমেন্ট মেচ করে, এবং যদি এটি কাস্টম শর্ত পূর্ণ করে তবেtrueফেরত দেয়।appendTo(StringBuffer buffer): এটি ম্যাচারের একটি টেক্সট রিপ্রেজেন্টেশন তৈরি করতে ব্যবহৃত হয় (ডিবাগিং বা লগিং জন্য)।
Custom Argument Matcher তৈরি করার ধাপ:
- ArgumentMatcher ইন্টারফেস ইমপ্লিমেন্ট করুন।
matches()মেথডে কাস্টম লজিক তৈরি করুন।appendTo()মেথডে প্রয়োজনীয় ডিবাগging স্টেটমেন্ট যোগ করুন।
উদাহরণ: Custom Argument Matcher তৈরি করা
ধরা যাক, আমাদের একটি PaymentService ক্লাস রয়েছে এবং আমরা PaymentGateway এর processPayment() মেথডে কাস্টম আর্গুমেন্ট ম্যাচিং করতে চাই। আমরা এমন একটি কাস্টম ম্যাচার তৈরি করব যা amount এর মান যাচাই করবে এবং তা যদি greater than 100 হয়, তবে আমরা তা মক করে সঠিক আউটপুট ফেরত দেব।
১. PaymentGateway ক্লাস (Dependency)
public class PaymentGateway {
public boolean processPayment(int amount) {
// Payment processing logic
return amount > 100; // Simulating successful payment for amounts > 100
}
}
২. PaymentService ক্লাস (Class Under Test)
public class PaymentService {
private PaymentGateway paymentGateway;
public PaymentService(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
public String makePayment(int amount) {
boolean success = paymentGateway.processPayment(amount);
return success ? "Payment successful" : "Payment failed";
}
}
৩. Custom Argument Matcher
import org.easymock.ArgumentMatcher;
// Custom Argument Matcher Class
class GreaterThan100Matcher implements ArgumentMatcher<Integer> {
@Override
public boolean matches(Integer argument) {
return argument != null && argument > 100;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("greater than 100");
}
}
৪. Unit Test with Custom Argument Matcher
import static org.easymock.EasyMock.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class PaymentServiceTest {
@Test
public void testPaymentWithCustomArgumentMatcher() {
// Create a mock object for PaymentGateway
PaymentGateway mockPaymentGateway = createMock(PaymentGateway.class);
// Set up expectation using the custom argument matcher
expect(mockPaymentGateway.processPayment(argThat(new GreaterThan100Matcher()))).andReturn(true);
replay(mockPaymentGateway);
// Create PaymentService instance with the mock PaymentGateway
PaymentService paymentService = new PaymentService(mockPaymentGateway);
// Call the method under test with amount 150
String result = paymentService.makePayment(150);
// Assert that the payment was successful
assertEquals("Payment successful", result);
// Verify that the mock method was called
verify(mockPaymentGateway);
}
@Test
public void testPaymentWithInvalidAmount() {
// Create a mock object for PaymentGateway
PaymentGateway mockPaymentGateway = createMock(PaymentGateway.class);
// Set up expectation using the custom argument matcher for invalid amount
expect(mockPaymentGateway.processPayment(argThat(new GreaterThan100Matcher()))).andReturn(true);
replay(mockPaymentGateway);
// Create PaymentService instance with the mock PaymentGateway
PaymentService paymentService = new PaymentService(mockPaymentGateway);
// Call the method under test with amount 50
String result = paymentService.makePayment(50);
// Assert that the payment was not successful
assertEquals("Payment failed", result);
// Verify that the mock method was called
verify(mockPaymentGateway);
}
}
ব্যাখ্যা:
- GreaterThan100Matcher: এই ক্লাসটি ArgumentMatcher ইন্টারফেসকে ইমপ্লিমেন্ট করে এবং
matches()মেথডে কাস্টম লজিক দেয় যা amount এর মান100এর চেয়ে বেশি কিনা যাচাই করে। - Unit Test: এখানে, processPayment() মেথডে
argThat()ব্যবহার করে কাস্টম ম্যাচারকে যুক্ত করা হয়েছে, যা PaymentService ক্লাসে PaymentGateway এর মক অবজেক্টের জন্য কাস্টম আর্গুমেন্ট যাচাই করে।- প্রথম টেস্টে 150 টাকা দিয়ে সফল পেমেন্ট পরীক্ষা করা হয়েছে।
- দ্বিতীয় টেস্টে 50 টাকা দিয়ে ব্যর্থ পেমেন্ট পরীক্ষা করা হয়েছে।
Test Case 1 (Valid Payment):
- Input:
150টাকা - Expected Output:
"Payment successful" - Explanation: 150 টাকা দিয়ে greater than 100 চেক সফল হয়েছে এবং পেমেন্ট সফল হয়েছে।
Test Case 2 (Invalid Payment):
- Input:
50টাকা - Expected Output:
"Payment failed" - Explanation: 50 টাকা দিয়ে greater than 100 চেক ব্যর্থ হয়েছে এবং পেমেন্ট ব্যর্থ হয়েছে।
EasyMock এ Custom Argument Matcher এর সুবিধা:
- Custom Validation: আপনি যেকোনো আর্গুমেন্টের জন্য কাস্টম লজিক তৈরি করতে পারেন যা ডিফল্ট ম্যাচার দ্বারা সঠিকভাবে যাচাই করা সম্ভব নয়।
- Code Maintainability: আপনার টেস্ট কোডে জটিল লজিক প্রয়োগ করতে সহায়তা করে, যেটি পরে পরিবর্তন বা সম্প্রসারণ সহজ করে তোলে।
- Reusability: একবার কাস্টম ম্যাচার তৈরি করলে তা পুনঃব্যবহারযোগ্য হয় এবং বিভিন্ন টেস্ট কেসে প্রয়োগ করা যায়।
EasyMock এ Custom Argument Matcher এর সীমাবদ্ধতা:
- Complexity: কাস্টম ম্যাচার তৈরি করা কিছুটা জটিল হতে পারে, বিশেষ করে যখন আর্গুমেন্টের অনেক ধরণ বা জটিল যাচাইয়ের প্রয়োজন হয়।
- Readability: কিছু ক্ষেত্রে, কাস্টম ম্যাচারের লজিক সঠিকভাবে বোঝা কঠিন হতে পারে, বিশেষত যখন অনেক ম্যাচার একত্রে ব্যবহার করা হয়।
সারাংশ
EasyMock ব্যবহার করে আপনি Custom Argument Matcher তৈরি করতে পারেন, যা আপনাকে আপনার ইউনিট টেস্টে আর্গুমেন্ট যাচাই করার জন্য নির্দিষ্ট শর্তাবলী প্রয়োগ করতে সাহায্য করে। এটি বিশেষ করে তখন উপকারী যখন ডিফল্ট আর্গুমেন্ট ম্যাচারগুলি পর্যাপ্ত নয় বা আরও বেশি কাস্টমাইজেশনের প্রয়োজন হয়। EasyMock এর মাধ্যমে আপনি সুনির্দিষ্টভাবে exception handling অথবা validation এর শর্তাবলী মক অবজেক্টে প্রয়োগ করতে পারেন, যা আপনার কোডের পরীক্ষণ আরো শক্তিশালী এবং বিশ্বাসযোগ্য করে তোলে।
EasyMock হল একটি জাভা লাইব্রেরি যা unit testing তে mock objects তৈরি করার জন্য ব্যবহৃত হয়। কখনও কখনও, যখন আমরা মক অবজেক্ট তৈরি করি, তখন আমাদের complex objects বা objects with multiple fields মক করতে হয়, যেমন lists, maps, অথবা কাস্টম ক্লাসের অবজেক্ট। EasyMock আমাদের complex object matching বা argument matching করার জন্য বেশ কিছু শক্তিশালী কৌশল সরবরাহ করে।
এই টিউটোরিয়ালে, আমরা EasyMock এ complex object matching এর বিভিন্ন কৌশল এবং তাদের ব্যবহার দেখবো।
1. Argument Matchers in EasyMock
EasyMock এ আপনি যখন মক অবজেক্টের মেথড স্টাব করেন, তখন আপনাকে আর্গুমেন্ট ম্যাচার ব্যবহার করতে হতে পারে, যা complex objects এর ক্ষেত্রেও কার্যকরী হয়। এই আর্গুমেন্ট ম্যাচারগুলি easyMock কে আপনার টেস্টের জন্য অগ্রিম নির্ধারিত আচরণ সম্পর্কে জানানোর জন্য ব্যবহার করা হয়।
কিছু সাধারণ argument matchers:
- anyObject(): যেকোনো অবজেক্টের জন্য মেট করে।
- eq(): নির্দিষ্ট মানের জন্য ম্যাচ করে।
- any(): যেকোনো ধরনের আর্গুমেন্টের জন্য ম্যাচ করে।
- isA(): নির্দিষ্ট শ্রেণী বা টাইপের জন্য ম্যাচ করে।
- notNull(): শুধুমাত্র non-null আর্গুমেন্টের জন্য ম্যাচ করে।
2. Complex Object Matching Techniques
2.1 Matching Complex Objects with anyObject()
anyObject() ব্যবহার করা হয় যখন আপনি একটি complex object বা custom class এর মেথড কলের জন্য যেকোনো অবজেক্ট মেনে নেন।
উদাহরণ: Matching Complex Objects with anyObject()
import static org.easymock.EasyMock.*;
public class ComplexObjectMatchingExample {
public static void main(String[] args) {
// Create a mock object
MyService mockService = createMock(MyService.class);
// Stubbing a method with complex object matching
expect(mockService.processData(anyObject(MyData.class))).andReturn("Processed");
// Activate the mock object
replay(mockService);
// Testing the method with any object of MyData class
MyData data = new MyData("example", 123);
System.out.println(mockService.processData(data)); // Should return "Processed"
// Verify interactions
verify(mockService);
}
}
// Complex object
class MyData {
private String name;
private int value;
public MyData(String name, int value) {
this.name = name;
this.value = value;
}
// Getters and setters
}
// Service to be mocked
interface MyService {
String processData(MyData data);
}
ব্যাখ্যা:
- anyObject(MyData.class) ব্যবহার করা হয়েছে যাতে processData() মেথডে যে কোনো MyData অবজেক্ট গ্রহণ করা যায়।
আউটপুট:
Processed
2.2 Matching Specific Fields with eq()
eq() ব্যবহার করা হয় যদি আপনি একটি নির্দিষ্ট মানের সাথে ম্যাচ করতে চান। এটি সাধারণত primitive types বা strings এর জন্য ব্যবহার করা হয়, তবে complex objects এর ক্ষেত্রেও কাজ করতে পারে যদি আপনি তাদের ফিল্ডের মানের সাথে মিলানোর চেষ্টা করেন।
উদাহরণ: Matching Specific Fields with eq()
import static org.easymock.EasyMock.*;
public class ComplexObjectFieldMatchingExample {
public static void main(String[] args) {
// Create a mock object
MyService mockService = createMock(MyService.class);
// Stubbing method with matching specific field
expect(mockService.processData(eq(new MyData("example", 123)))).andReturn("Valid Data");
// Activate the mock object
replay(mockService);
// Testing the method with exact matching
MyData data = new MyData("example", 123);
System.out.println(mockService.processData(data)); // Should return "Valid Data"
// Verify interactions
verify(mockService);
}
}
ব্যাখ্যা:
- eq() এর মাধ্যমে আমরা নিশ্চিত করেছি যে processData() মেথড শুধুমাত্র সেই MyData অবজেক্ট মেনে নিবে যার name "example" এবং value 123।
আউটপুট:
Valid Data
2.3 Using isA() to Match Objects by Type
isA() ব্যবহার করে আপনি একটি অবজেক্টের টাইপের সাথে ম্যাচ করতে পারেন। এটি একটি সাধারণ উপায়, যেখানে আপনি একটি নির্দিষ্ট শ্রেণী বা ইন্টারফেস টাইপের অবজেক্ট মেনে নেন।
উদাহরণ: Matching Object by Type with isA()
import static org.easymock.EasyMock.*;
public class TypeMatchingExample {
public static void main(String[] args) {
// Create a mock object
MyService mockService = createMock(MyService.class);
// Stubbing method to match by type
expect(mockService.processData(isA(MyData.class))).andReturn("Type Matched");
// Activate the mock object
replay(mockService);
// Testing with MyData type object
MyData data = new MyData("test", 456);
System.out.println(mockService.processData(data)); // Should return "Type Matched"
// Verify interactions
verify(mockService);
}
}
ব্যাখ্যা:
- isA(MyData.class) ব্যবহার করা হয়েছে, যা নিশ্চিত করে যে processData() মেথডটি শুধুমাত্র MyData টাইপের অবজেক্ট গ্রহণ করবে।
আউটপুট:
Type Matched
2.4 Matching Arguments Using notNull()
কখনও কখনও, আপনি চান যে মক অবজেক্ট কোনো non-null আর্গুমেন্ট মেনে নিক। এ ক্ষেত্রে notNull() ব্যবহার করা যেতে পারে।
উদাহরণ: Matching Non-Null Arguments with notNull()
import static org.easymock.EasyMock.*;
public class NonNullArgumentExample {
public static void main(String[] args) {
// Create a mock object
MyService mockService = createMock(MyService.class);
// Stubbing with not null argument matcher
expect(mockService.processData(notNull())).andReturn("Non-null Data");
// Activate the mock object
replay(mockService);
// Testing with non-null object
MyData data = new MyData("valid", 789);
System.out.println(mockService.processData(data)); // Should return "Non-null Data"
// Verify interactions
verify(mockService);
}
}
ব্যাখ্যা:
- notNull() ব্যবহার করে আমরা নিশ্চিত করেছি যে processData() মেথডটি শুধুমাত্র non-null আর্গুমেন্ট মেনে নেবে।
আউটপুট:
Non-null Data
3. Complex Object Matching with Custom Matchers
EasyMock-এ আপনি কাস্টম ম্যাচার তৈরি করতে পারেন যদি আপনি আরো জটিল বা কাস্টম কন্ডিশন দিয়ে আর্গুমেন্ট ম্যাচ করতে চান।
উদাহরণ: Using a Custom Matcher
import static org.easymock.EasyMock.*;
import org.easymock.IArgumentMatcher;
public class CustomMatcherExample {
public static void main(String[] args) {
// Create a mock object
MyService mockService = createMock(MyService.class);
// Stubbing with custom matcher
expect(mockService.processData(withMatcher(new MyDataMatcher("test", 123)))).andReturn("Custom Match");
// Activate the mock object
replay(mockService);
// Testing with custom matcher
MyData data = new MyData("test", 123);
System.out.println(mockService.processData(data)); // Should return "Custom Match"
// Verify interactions
verify(mockService);
}
}
// Custom matcher class
class MyDataMatcher implements IArgumentMatcher {
private String expectedName;
private int expectedValue;
public MyDataMatcher(String name, int value) {
this.expectedName = name;
this.expectedValue = value;
}
@Override
public boolean matches(Object argument) {
if (argument instanceof MyData) {
MyData data = (MyData) argument;
return data.getName().equals(expectedName) && data.getValue() == expectedValue;
}
return false;
}
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("Custom MyDataMatcher");
}
}
ব্যাখ্যা:
- MyDataMatcher ক্লাসটি IArgumentMatcher ইন্টারফেসের বাস্তবায়ন, যা কাস্টম ম্যাচিং লজিক প্রদান করে।
- matches() মেথডের মাধ্যমে আপনি নিজের শর্তাবলী অনুযায়ী আর্গুমেন্ট ম্যাচ করতে পারেন।
আউটপুট:
Custom Match
EasyMock আপনাকে complex object matching এর জন্য শক্তিশালী কৌশল সরবরাহ করে, যার মাধ্যমে আপনি mock objects এর আর্গুমেন্টের সাথে একাধিক ভিন্ন ধরণের ম্যাচিং করতে পারেন। এর মধ্যে anyObject(), eq(), isA(), notNull() এবং custom matchers ব্যবহার করে আপনি complex objects এর সাথে সহজে টেস্টিং করতে পারেন।
এই কৌশলগুলি ব্যবহার করে আপনি unit tests কে আরও কার্যকরী, নির্ভুল এবং রক্ষণাবেক্ষণযোগ্য করতে পারেন, যেহেতু আপনি কোনো নির্দিষ্ট অবজেক্টের আচরণ মক করে যাচাই করতে পারেন।
Read more