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