EasyMock একটি জনপ্রিয় লাইব্রেরি যা জাভাতে মকিং এবং স্টাবিং করার জন্য ব্যবহৃত হয়, বিশেষত ইউনিট টেস্টে। এটি একক (unit) পরীক্ষা করার জন্য ডিপেনডেন্সি মকিংয়ে সহায়তা করে, যেখানে নির্দিষ্ট অবজেক্টের আচরণ নির্ধারণ করা যায় এবং টেস্টিং এর জন্য সেই আচরণ অনুসারে ফলাফল পাওয়া যায়। Mock objects বা মক অবজেক্ট হচ্ছে আসল অবজেক্টের একটি কপি যা শুধুমাত্র নির্দিষ্ট আচরণ বা ফলাফল ফেরত দেয়, কিন্তু এটি বাস্তবে কোনো কার্যকলাপ বা প্রক্রিয়া সম্পাদন করে না।
এখানে EasyMock ব্যবহার করে Mock Object তৈরি করার প্রক্রিয়া এবং উদাহরণ দেওয়া হয়েছে।
1. EasyMock দিয়ে Mock Object তৈরি
EasyMock দিয়ে একটি Mock Object তৈরি করার জন্য কয়েকটি সহজ ধাপ অনুসরণ করতে হয়:
- Mock Object তৈরি করা:
EasyMock.createMock()মেথড ব্যবহার করে মক অবজেক্ট তৈরি করা হয়। - স্টাবিং (Stubbing): মক অবজেক্টের জন্য প্রত্যাশিত আচরণ নির্ধারণ করা হয়, যেমন কোন মেথডে কোন রিটার্ন ভ্যালু দেওয়া হবে।
- রিপ্লে (Replay): মক অবজেক্টের আচরণ সক্রিয় করা হয়, যা স্টাবিং-এর পরপরেই কল করা হয়।
- ভেরিফিকেশন (Verification): মক অবজেক্টের উপর নির্ধারিত আচরণ এবং মেথড কল নিশ্চিত করা হয়।
2. উদাহরণ: EasyMock দিয়ে Mock Object তৈরি
এখানে আমরা একটি Calculator ইন্টারফেস তৈরি করে তার মক অবজেক্ট তৈরি করব এবং তার ওপর কিছু স্টাবিং করব।
Step 1: Maven Dependency (যদি Maven ব্যবহার করা হয়)
যদি আপনি Maven ব্যবহার করেন, তাহলে pom.xml এ EasyMock ডিপেনডেন্সি যোগ করতে হবে।
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>4.3</version> <!-- Latest version -->
<scope>test</scope>
</dependency>
Step 2: মক অবজেক্ট তৈরি ও স্টাবিং
এখন, আমরা Calculator ইন্টারফেস এবং তার মক অবজেক্ট তৈরি করব।
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class EasyMockExample {
// Interface to be mocked
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
}
@Test
public void testCalculator() {
// Step 1: Create a mock object for the Calculator interface
Calculator mockCalculator = EasyMock.createMock(Calculator.class);
// Step 2: Define the expected behavior for the mock object
EasyMock.expect(mockCalculator.add(2, 3)).andReturn(5); // Stubbing add method
EasyMock.expect(mockCalculator.subtract(5, 3)).andReturn(2); // Stubbing subtract method
// Step 3: Activate the mock object (switch to replay mode)
EasyMock.replay(mockCalculator);
// Step 4: Use the mock object
int additionResult = mockCalculator.add(2, 3);
int subtractionResult = mockCalculator.subtract(5, 3);
// Step 5: Assert the results
assertEquals(5, additionResult); // Test for add method
assertEquals(2, subtractionResult); // Test for subtract method
// Step 6: Verify that the mock object was used correctly
EasyMock.verify(mockCalculator); // Verify that methods were called as expected
}
}
Step 3: ব্যাখ্যা
- Mock Object তৈরি:
EasyMock.createMock(Calculator.class)মেথড ব্যবহার করেCalculatorইন্টারফেসের একটি মক অবজেক্ট তৈরি করা হয়েছে।
- স্টাবিং (Stubbing):
EasyMock.expect(mockCalculator.add(2, 3)).andReturn(5)এই স্টেটমেন্টে আমরা নির্ধারণ করেছি যে, যখনadd(2, 3)কল হবে, তখন এটি ৫ রিটার্ন করবে।- একইভাবে,
subtract(5, 3)মেথডের জন্য ২ রিটার্ন করার জন্য স্টাবিং করা হয়েছে।
- রিপ্লে (Replay):
EasyMock.replay(mockCalculator)মেথডটি মক অবজেক্টের আচরণ সক্রিয় করে দেয় এবং এরপর মক অবজেক্ট ব্যবহারের জন্য প্রস্তুত হয়।
- ভেরিফিকেশন (Verification):
EasyMock.verify(mockCalculator)মেথডটি নিশ্চিত করে যে মক অবজেক্টটি সঠিকভাবে কল হয়েছে এবং প্রত্যাশিত আচরণ অনুযায়ী কাজ করেছে।
3. আরও কিছু উদাহরণ
3.1. Return Multiple Values (একাধিক মান রিটার্ন)
কখনও কখনও, মক অবজেক্টের মেথড একাধিক কলের জন্য বিভিন্ন মান রিটার্ন করতে পারে। EasyMock এ এটি করতে andReturn() চেইন করা যায়।
EasyMock.expect(mockCalculator.add(2, 3)).andReturn(5).andReturn(7);
এখানে, প্রথমবার add(2, 3) কল করলে ৫ রিটার্ন হবে এবং দ্বিতীয়বার কল করলে ৭ রিটার্ন হবে।
3.2. Throwing Exceptions (এক্সেপশন ছুঁড়ে দেওয়া)
এছাড়া, আপনি মক অবজেক্টে কোনো এক্সেপশনও ছুঁড়ে দিতে পারেন।
EasyMock.expect(mockCalculator.add(2, -1)).andThrow(new IllegalArgumentException("Invalid input"));
এটি নির্দিষ্ট আর্গুমেন্টের জন্য IllegalArgumentException এক্সেপশন ছুঁড়ে দেবে।
4. সারাংশ
EasyMock ব্যবহার করে আপনি সহজেই Mock Objects তৈরি করতে পারেন এবং তাদের আচরণ নির্ধারণ করতে পারেন। এটি বিশেষভাবে ইউনিট টেস্টিংয়ের জন্য উপযোগী, যেখানে আপনি আসল অবজেক্টের আচরণ ছাড়াই একটি নির্দিষ্ট ফাংশনালিটি পরীক্ষা করতে পারেন। EasyMock এর মকিং, স্টাবিং, এবং ভেরিফিকেশন ফিচারগুলি টেস্টিংয়ের কার্যকারিতা এবং গুণগত মান বৃদ্ধি করতে সহায়ক।
Mock Object হল একটি ডামি বা প্লেসহোল্ডার অবজেক্ট যা ইউনিট টেস্টিংয়ে ব্যবহার করা হয়। এটি মূলত নির্দিষ্ট আচরণ বা কার্যকারিতা তৈরি করে, তবে এটি বাস্তব অবজেক্টের মতো পুরোপুরি কাজ করে না। মক অবজেক্ট ব্যবহারের মাধ্যমে, টেস্টিংয়ের সময় বাস্তব ডিপেনডেন্সি (যেমন ডাটাবেস, নেটওয়ার্ক, বা অন্যান্য সিস্টেম) এড়ানো হয়, এবং শুধু আপনার কোডের লজিক টেস্ট করা হয়।
EasyMock হল একটি লাইব্রেরি যা মক অবজেক্ট তৈরি এবং ব্যবহার করার জন্য সহজ এবং কার্যকরী উপায় প্রদান করে। এটি শুধুমাত্র নির্দিষ্ট মেথড কলগুলির জন্য মক অবজেক্ট তৈরি করতে এবং তাদের আচরণ সংজ্ঞায়িত করতে সহায়ক।
1. Mock Object কি?
Mock Object হলো একটি টেস্টিং কৌশল যা কিছু নির্দিষ্ট ডিপেনডেন্সি বা ক্লাসের আচরণ অনুকরণ করতে ব্যবহৃত হয়। এটি মূলত বাস্তব অবজেক্টের বিকল্প হিসেবে কাজ করে, কিন্তু বাস্তব কার্যকারিতা থাকে না। টেস্টিংয়ের সময়ে মক অবজেক্ট ব্যবহার করা হয় যাতে কিছু নির্দিষ্ট অংশের আচরণ পরীক্ষা করা যায় এবং সফটওয়্যারটি অন্যান্য অংশের উপর নির্ভর না করে কাজ করতে পারে।
Mock Object এর উদ্দেশ্য:
- Isolation: মক অবজেক্টগুলি মূল সিস্টেম থেকে পৃথকভাবে পরীক্ষা করার সুযোগ দেয়।
- Control: টেস্টের সময় অবজেক্টের আচরণ নিয়ন্ত্রণ করা যায়, যা বাস্তব অবজেক্টে সম্ভব নয়।
- Focus on Logic: টেস্টটি কোডের লজিক এবং ব্যবসায়িক নিয়মে মনোযোগ দেয়, বাস্তব ডিপেনডেন্সির মধ্যে আটকে না পড়ে।
Mock Object এর ব্যবহার ক্ষেত্র:
- Database: ইউনিট টেস্টিংয়ে ডাটাবেস অপারেশন এড়িয়ে মক ডাটাবেস ব্যবহার।
- Web Services: API বা সার্ভিস কলের বদলে মক সার্ভিস ব্যবহার।
- External Systems: বাইরের সিস্টেমে যোগাযোগের পরিবর্তে মক অবজেক্ট ব্যবহার।
2. EasyMock দিয়ে Mock Object তৈরি করা
EasyMock ব্যবহার করে মক অবজেক্ট তৈরি করা খুবই সহজ। এখানে একটি সাধারণ পদ্ধতি দেওয়া হয়েছে:
2.1 EasyMock লাইব্রেরি অন্তর্ভুক্ত করা
প্রথমে, আপনাকে Maven প্রজেক্টে EasyMock অন্তর্ভুক্ত করতে হবে। pom.xml ফাইলে নিম্নলিখিত ডিপেনডেন্সি যোগ করুন:
<dependencies>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>4.3</version> <!-- Latest version -->
<scope>test</scope>
</dependency>
</dependencies>
2.2 EasyMock দিয়ে Mock Object তৈরি করা
এখন, আসুন একটি উদাহরণ দেখি যেখানে EasyMock ব্যবহার করে একটি মক অবজেক্ট তৈরি করা হয়েছে।
উদাহরণ: একটি DatabaseService ইন্টারফেসের জন্য মক অবজেক্ট তৈরি করা।
import org.easymock.EasyMock;
import org.junit.Test;
import static org.easymock.EasyMock.*;
public class EasyMockExample {
// Sample interface to be mocked
public interface DatabaseService {
String fetchData();
}
@Test
public void testDatabaseService() {
// Create mock object for DatabaseService
DatabaseService mockDatabaseService = EasyMock.createMock(DatabaseService.class);
// Define behavior for mock object
expect(mockDatabaseService.fetchData()).andReturn("Mock Data");
// Activate the mock
replay(mockDatabaseService);
// Use the mock object in your code
String result = mockDatabaseService.fetchData();
System.out.println("Fetched data: " + result); // Should print: Fetched data: Mock Data
// Verify that all expected methods were called on the mock
verify(mockDatabaseService);
}
}
ব্যাখ্যা:
- Mock Creation:
EasyMock.createMock(DatabaseService.class)দ্বারা একটি মক অবজেক্ট তৈরি করা হয়েছে। - Behavior Definition:
expect(mockDatabaseService.fetchData()).andReturn("Mock Data")এর মাধ্যমে আমরা নির্দিষ্ট মেথডের জন্য রিটার্ন ভ্যালু ডিফাইন করেছি। - Replay:
replay(mockDatabaseService)মক অবজেক্টটি সক্রিয় করে, যাতে এটি মেথড কলগুলোর জন্য প্রস্তুত থাকে। - Verification:
verify(mockDatabaseService)ব্যবহার করে আমরা নিশ্চিত হয়েছি যে সমস্ত প্রত্যাশিত মেথড কল হয়েছে।
3. Mock Object এর ব্যবহার এবং Test Case
Mocking Dependencies:
ধরা যাক, আপনার একটি ক্লাস UserService আছে যা DatabaseService এর উপর নির্ভরশীল। আমরা মক অবজেক্ট ব্যবহার করে DatabaseService এর behavior টেস্ট করব।
Example: UserService ক্লাসের জন্য Test Case
// DatabaseService Interface
public interface DatabaseService {
String fetchUserData(int userId);
}
// UserService Class, which depends on DatabaseService
public class UserService {
private DatabaseService databaseService;
public UserService(DatabaseService databaseService) {
this.databaseService = databaseService;
}
public String getUserInfo(int userId) {
return databaseService.fetchUserData(userId);
}
}
// Test Case for UserService
import org.easymock.EasyMock;
import org.junit.Test;
import static org.easymock.EasyMock.*;
public class UserServiceTest {
@Test
public void testGetUserInfo() {
// Create a mock of DatabaseService
DatabaseService mockDatabaseService = createMock(DatabaseService.class);
// Define the behavior of the mock
expect(mockDatabaseService.fetchUserData(1)).andReturn("User Data for ID 1");
// Activate the mock
replay(mockDatabaseService);
// Create an instance of UserService with the mock DatabaseService
UserService userService = new UserService(mockDatabaseService);
// Test the UserService method
String result = userService.getUserInfo(1);
System.out.println(result); // Should print: User Data for ID 1
// Verify the interactions with the mock
verify(mockDatabaseService);
}
}
ব্যাখ্যা:
- এখানে UserService ক্লাস
DatabaseServiceএর উপর নির্ভরশীল, এবং আমরা DatabaseService এর মক অবজেক্ট ব্যবহার করে UserService এরgetUserInfo()মেথড টেস্ট করেছি। expect()মেথড দিয়ে মক অবজেক্টের আচরণ ডিফাইন করা হয়েছে এবংreplay()মেথড ব্যবহার করে মক অবজেক্টটি সক্রিয় করা হয়েছে।- verify() মেথড ব্যবহার করে নিশ্চিত হওয়া হয়েছে যে মক অবজেক্টের উপর নির্ধারিত মেথডটি কল হয়েছে।
4. Mocking with Argument Matchers
EasyMock ব্যবহার করে আপনি আর্গুমেন্ট ম্যাচার (Argument Matcher) ব্যবহার করে মকিং আরও নির্দিষ্টভাবে করতে পারেন।
Example:
import org.easymock.EasyMock;
import org.junit.Test;
import static org.easymock.EasyMock.*;
public class ArgumentMatcherExample {
public interface PaymentService {
void processPayment(String accountId, double amount);
}
@Test
public void testPaymentService() {
PaymentService mockPaymentService = createMock(PaymentService.class);
// Argument Matcher used to match the argument
mockPaymentService.processPayment(eq("12345"), gt(1000.0));
// Activate the mock
replay(mockPaymentService);
// Test method with matching arguments
mockPaymentService.processPayment("12345", 1500.0); // This will match
// Verify
verify(mockPaymentService);
}
}
ব্যাখ্যা:
eq("12345")এবংgt(1000.0)ব্যবহার করে আর্গুমেন্ট ম্যাচার ব্যবহার করা হয়েছে, যা নিশ্চিত করে যে মক অবজেক্টটি কেবল নির্দিষ্ট আর্গুমেন্টের সাথে কাজ করবে।
Mock Object হল সফটওয়্যার টেস্টিংয়ের একটি গুরুত্বপূর্ণ কৌশল যা টেস্টের সময় বাস্তব ডিপেনডেন্সির পরিবর্তে মক অবজেক্ট ব্যবহার করে নির্দিষ্ট আচরণ পরীক্ষা করা হয়। EasyMock Java তে মক অবজেক্ট তৈরির জন্য একটি শক্তিশালী লাইব্রেরি। এটি কোডের টেস্টিং সহজ করে, কারণ আপনি কোডের লজিক পরীক্ষা করতে পারেন যখন বাহ্যিক সিস্টেমগুলির প্রভাব এড়ানো হয়।
EasyMock আপনাকে মক অবজেক্ট তৈরি করার, আচরণ নির্ধারণ করার এবং টেস্টে তাদের ব্যবহার করার মাধ্যমে সিস্টেমের নির্ভরশীলতা কমিয়ে দেয় এবং ইউনিট টেস্টিংয়ের কার্যকারিতা বৃদ্ধি করে।
EasyMock.createMock() এবং EasyMock.createNiceMock() কি?
EasyMock.createMock() এবং EasyMock.createNiceMock() উভয়ই EasyMock লাইব্রেরির মেথড, যা মক অবজেক্ট তৈরি করতে ব্যবহৃত হয়। মক অবজেক্ট হলো এমন একটি অবজেক্ট যা আসল অবজেক্টের মতো আচরণ করে, তবে এতে কিছু নির্দিষ্ট আচরণ, যেমন মেথড কল, নির্ধারণ করা হয় এবং পরীক্ষা করা হয়।
- EasyMock.createMock(): এটি একটি সাধারণ মক অবজেক্ট তৈরি করে, যা শুধুমাত্র পূর্বনির্ধারিত আচরণ বা প্রত্যাশিত ফলাফল (expectations) অনুসরণ করে।
- EasyMock.createNiceMock(): এটি একটি "nice" মক অবজেক্ট তৈরি করে। এর মানে হল যে, যদি মক অবজেক্টে কোন মেথড কল করা হয় যা পূর্বে প্রত্যাশিত হয়নি, তবে এটি একটি ডিফল্ট ভ্যালু প্রদান করবে (যেমন
nullবা0), এবং এর মাধ্যমে কোনোUnexpectedMethodCallExceptionতৈরি হবে না। এটি সাধারণত সেই সময় ব্যবহৃত হয় যখন আপনি কিছু মক অবজেক্টের জন্য মক আপডেট চান কিন্তু আপনি সব মেথড কলের জন্য প্রত্যাশিত আচরণ তৈরি করতে চান না।
1. EasyMock.createMock()
EasyMock.createMock() মেথডটি একটি মক অবজেক্ট তৈরি করে, যার সাথে আপনি expect() মেথড ব্যবহার করে কিছু নির্দিষ্ট আচরণ বা প্রত্যাশা সেট করতে পারেন। এটি শুধুমাত্র সেই মেথডগুলিকে অনুমোদন করে যেগুলি আপনি পূর্বে প্রত্যাশিত করেছেন, এবং অন্য কোন মেথড কল হলে এটি একটি UnexpectedMethodCallException ছুড়ে দেয়।
উদাহরণ:
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.*;
public class EasyMockExampleTest {
public interface Service {
String greet(String name);
String farewell(String name);
}
@Test
public void testCreateMock() {
// Creating a mock object using createMock()
Service serviceMock = EasyMock.createMock(Service.class);
// Setting up expectations
EasyMock.expect(serviceMock.greet("John")).andReturn("Hello, John!");
EasyMock.expect(serviceMock.farewell("John")).andReturn("Goodbye, John!");
// Activating the mock
EasyMock.replay(serviceMock);
// Test the mock behavior
String greetResult = serviceMock.greet("John");
String farewellResult = serviceMock.farewell("John");
// Verifying the results
assertEquals("Hello, John!", greetResult);
assertEquals("Goodbye, John!", farewellResult);
// Verifying that the mock was used as expected
EasyMock.verify(serviceMock);
}
}
ব্যাখ্যা:
- EasyMock.createMock(Service.class): এটি
Serviceইন্টারফেসের একটি মক অবজেক্ট তৈরি করেছে। - EasyMock.expect(): এটি নির্ধারণ করে যে
greet("John")এবংfarewell("John")মেথড কলগুলির প্রত্যাশিত ফলাফল কী হবে। - EasyMock.replay(): এটি মক অবজেক্টে সেট করা প্রত্যাশা সক্রিয় করে।
- EasyMock.verify(): এটি যাচাই করে যে মক অবজেক্টটির প্রত্যাশিত মেথড কলগুলি সঠিকভাবে হয়েছে কিনা।
2. EasyMock.createNiceMock()
EasyMock.createNiceMock() মেথডটি একটি "nice" মক অবজেক্ট তৈরি করে। এর বৈশিষ্ট্য হল, যদি কোনো মেথড কল করা হয় যেটি পূর্বে প্রত্যাশিত হয় না, তবে এটি ডিফল্ট মান ফেরত দেয় (যেমন null, 0, false ইত্যাদি), এবং কোন ত্রুটি ছাড়াই এটি চলে।
এটি সাধারণত তখন ব্যবহৃত হয় যখন আপনি কিছু মক অবজেক্টের জন্য আচরণ নির্ধারণ করতে চান, তবে সব মেথডের জন্য প্রত্যাশা নির্ধারণ করতে চান না।
উদাহরণ:
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.*;
public class EasyMockExampleTest {
public interface Service {
String greet(String name);
String farewell(String name);
}
@Test
public void testCreateNiceMock() {
// Creating a nice mock object using createNiceMock()
Service serviceMock = EasyMock.createNiceMock(Service.class);
// Setting up expectations for greet method
EasyMock.expect(serviceMock.greet("John")).andReturn("Hello, John!");
// Activating the mock
EasyMock.replay(serviceMock);
// Test the mock behavior
String greetResult = serviceMock.greet("John");
String farewellResult = serviceMock.farewell("John"); // No expectation set for this method
// Verifying the results
assertEquals("Hello, John!", greetResult);
assertNull(farewellResult); // No expectation set, should return null (default behavior)
// Verifying that the mock was used as expected
EasyMock.verify(serviceMock);
}
}
ব্যাখ্যা:
- EasyMock.createNiceMock(Service.class): এটি
Serviceইন্টারফেসের একটি nice মক অবজেক্ট তৈরি করেছে। - EasyMock.expect(): এটি
greet("John")মেথডের জন্য প্রত্যাশা নির্ধারণ করেছে। farewell("John")মেথডের জন্য কোনো প্রত্যাশা নির্ধারণ করা হয়নি, তাই এটিnullফেরত দিবে।- EasyMock.replay(): এটি মক অবজেক্টের আচরণ সক্রিয় করে।
- EasyMock.verify(): এটি যাচাই করে যে মক অবজেক্টটি সঠিকভাবে ব্যবহৃত হয়েছে কিনা।
EasyMock.createMock() এবং EasyMock.createNiceMock() এর মধ্যে পার্থক্য:
| Feature | EasyMock.createMock() | EasyMock.createNiceMock() |
|---|---|---|
| Default Behavior | এক্সপেকটেড মেথড কল ছাড়া কোনো কল হলে UnexpectedMethodCallException ঘটে। | এক্সপেকটেড মেথড কল ছাড়া কল হলে ডিফল্ট মান প্রদান করা হয় (যেমন null, 0, false) |
| Use Case | যখন আপনি সকল মেথড কলের জন্য প্রত্যাশা নির্ধারণ করতে চান। | যখন কিছু মেথডের জন্য প্রত্যাশা নির্ধারণ না করে ডিফল্ট মান দরকার। |
| Error Handling | মক অবজেক্টে কোনো অপ্রত্যাশিত কল হলে ত্রুটি হবে। | অপ্রত্যাশিত কলের জন্য ত্রুটি না দিয়ে ডিফল্ট মান প্রদান করবে। |
সারাংশ
- EasyMock.createMock() এবং EasyMock.createNiceMock() দুটি মক অবজেক্ট তৈরি করার জন্য ব্যবহৃত হয়।
- createMock() ব্যবহার করলে আপনি শুধু নির্দিষ্ট মেথডগুলির জন্য প্রত্যাশা তৈরি করতে পারেন এবং অন্য কোনো অপ্রত্যাশিত মেথড কল হলে
UnexpectedMethodCallExceptionঘটবে। - createNiceMock() ব্যবহার করলে, আপনি অপ্রত্যাশিত মেথড কলগুলির জন্য ডিফল্ট মান (যেমন
null,false,0) ফেরত পাবেন এবং এতে কোনো ত্রুটি ঘটবে না।
এটি মূলত টেস্টিং পরিস্থিতির উপর নির্ভর করে, আপনি কোন ধরনের মক অবজেক্ট প্রয়োজন তা অনুযায়ী এগুলির মধ্যে সঠিকটি নির্বাচন করবেন।
EasyMock হল একটি শক্তিশালী mocking framework যা Java টেস্টিংয়ের জন্য ব্যবহৃত হয়। এটি আপনাকে interface এবং class উভয়ের জন্য মক অবজেক্ট তৈরি করতে সাহায্য করে। মক অবজেক্টগুলি টেস্টিংয়ের সময় নির্ভরশীলতার আচরণ নকল (mock) করতে ব্যবহৃত হয়, যাতে আসল অবজেক্ট ব্যবহার না করে নির্দিষ্ট লজিক পরীক্ষা করা যায়।
এখানে আমরা দেখবো EasyMock ব্যবহার করে Interface এবং Class উভয়ের জন্য মক অবজেক্ট কীভাবে তৈরি করা যায়।
1. Interface এর জন্য Mock তৈরি
Interface এর জন্য মক তৈরি করার সময়, EasyMock createMock() মেথড ব্যবহার করে মক অবজেক্ট তৈরি করে। এই পদ্ধতিতে, মক অবজেক্টটি শুধু interface অনুযায়ী আচরণ করে, এবং আসল ক্লাসের কোনও বাস্তবায়ন প্রয়োজন হয় না।
1.1. Interface Mock Example
ধরা যাক আমাদের একটি PaymentService ইন্টারফেস রয়েছে, এবং আমরা এটি মক করতে চাই।
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.*;
interface PaymentService {
boolean processPayment(int amount);
}
// Test Class
public class InterfaceMockExample {
@Test
public void testProcessPayment() {
// Creating mock object for the interface
PaymentService paymentServiceMock = EasyMock.createMock(PaymentService.class);
// Defining behavior for the mock
EasyMock.expect(paymentServiceMock.processPayment(100)).andReturn(true);
// Activating the mock
EasyMock.replay(paymentServiceMock);
// Using the mock object
boolean paymentStatus = paymentServiceMock.processPayment(100);
// Asserting the result
assertTrue(paymentStatus);
// Verifying the mock interactions
EasyMock.verify(paymentServiceMock);
}
}
ব্যাখ্যা:
- PaymentService একটি সিম্পল ইন্টারফেস যা একটি পেমেন্ট প্রক্রিয়া করার জন্য একটি processPayment() মেথড ঘোষণা করে।
- EasyMock.createMock(PaymentService.class) এর মাধ্যমে আমরা ইন্টারফেসটির জন্য একটি মক অবজেক্ট তৈরি করেছি।
- EasyMock.expect() মেথডটি দিয়ে মক অবজেক্টের আচরণ নির্ধারণ করা হয়েছে, যেখানে আমরা বলেছি যে, যদি
processPayment(100)কল করা হয়, তাহলে এটি true রিটার্ন করবে। - EasyMock.replay() মক অবজেক্টটি কার্যকর করতে ব্যবহৃত হয়, এবং EasyMock.verify() মক অবজেক্টের সাথে সমস্ত ইন্টারঅ্যাকশন যাচাই করতে ব্যবহৃত হয়।
আউটপুট:
Test passed successfully.
2. Class এর জন্য Mock তৈরি
Class এর জন্য মক তৈরি করার সময়, আপনি EasyMock.createMock() ব্যবহার করতে পারেন, তবে EasyMock ক্লাসের জন্য partial mocking বা full mocking সমর্থন করে। অর্থাৎ, আপনি ক্লাসের কিছু মেথডের আচরণ মক করতে পারেন বা পুরো ক্লাসটিকে মক করতে পারেন।
2.1. Full Mocking for a Class Example
এখানে একটি Car ক্লাস রয়েছে, যা একটি Engine অবজেক্টের উপর নির্ভরশীল। আমরা এই Car ক্লাসের জন্য মক অবজেক্ট তৈরি করতে পারি।
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.*;
class Engine {
public void start() {
System.out.println("Engine started.");
}
}
class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void startCar() {
engine.start();
System.out.println("Car started.");
}
}
// Test Class
public class ClassMockExample {
@Test
public void testStartCar() {
// Create mock object for the Engine class
Engine engineMock = EasyMock.createMock(Engine.class);
// Define behavior for the mock object
engineMock.start();
EasyMock.expectLastCall().once();
// Activate the mock
EasyMock.replay(engineMock);
// Create Car object with the mock Engine
Car car = new Car(engineMock);
// Using the mock object
car.startCar();
// Verify the mock
EasyMock.verify(engineMock);
}
}
ব্যাখ্যা:
- Engine ক্লাসটি একটি সিম্পল ক্লাস যা start() মেথডে একটি কার্যকলাপ সম্পাদন করে।
- Car ক্লাসের startCar() মেথড Engine ক্লাসের start() মেথডের উপর নির্ভরশীল।
- আমরা Engine ক্লাসের জন্য মক অবজেক্ট তৈরি করেছি এবং Car ক্লাসের সাথে ব্যবহার করেছি। এটি নিশ্চিত করেছে যে Car ক্লাসের startCar() মেথডে Engine এর start() মেথডটি একবার কল হবে।
আউটপুট:
Engine started.
Car started.
2.2. Partial Mocking for a Class Example
EasyMock ক্লাসের partial mocking এর মাধ্যমে আপনি আসল ক্লাসের কিছু মেথড মক করতে পারেন, এবং কিছু মেথড আসলভাবে কাজ করতে দেয়।
import org.easymock.EasyMock;
import org.junit.Test;
import static org.junit.Assert.*;
class Engine {
public void start() {
System.out.println("Engine started.");
}
public void stop() {
System.out.println("Engine stopped.");
}
}
class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void startCar() {
engine.start();
System.out.println("Car started.");
}
public void stopCar() {
engine.stop();
System.out.println("Car stopped.");
}
}
// Test Class
public class PartialMockingExample {
@Test
public void testStartCar() {
// Create partial mock for Engine class
Engine engineMock = EasyMock.partialMockBuilder(Engine.class)
.addMockedMethod("start")
.createMock();
// Define behavior for the mock object
engineMock.start();
EasyMock.expectLastCall().once();
// Activate the mock
EasyMock.replay(engineMock);
// Create Car object with the mock Engine
Car car = new Car(engineMock);
// Using the mock object
car.startCar();
// Verify the mock
EasyMock.verify(engineMock);
}
}
ব্যাখ্যা:
- Engine ক্লাসের start() মেথডটি partial mock করা হয়েছে, এবং stop() মেথডটি আসলভাবে কাজ করবে।
- EasyMock.partialMockBuilder() মেথডটি ব্যবহার করে আমরা partial mock তৈরি করেছি এবং start() মেথডটি মক করেছি।
আউটপুট:
Engine started.
Car started.
3. Mocking Interface এবং Class এর জন্য EasyMock এর সুবিধা
- Interface Mocking: EasyMock ইন্টারফেসের জন্য মক তৈরি করতে খুবই কার্যকরী, কারণ এটি শুধুমাত্র ইন্টারফেসের আচরণ নির্ধারণ করে এবং আসল ক্লাসের কোনো বাস্তবায়ন প্রয়োজন হয় না।
- Class Mocking: ক্লাসের জন্য মক তৈরি করার সময়, আপনি full mock বা partial mock উভয়ই করতে পারেন, যা আপনার টেস্টিং এর জন্য অত্যন্ত নমনীয়তা প্রদান করে।
- Behavior Verification: আপনি মক অবজেক্টের আচরণ সুনির্দিষ্টভাবে নির্ধারণ এবং যাচাই করতে পারেন।
সারাংশ
EasyMock Java টেস্টিংয়ের জন্য একটি অত্যন্ত শক্তিশালী টুল যা আপনাকে interface এবং class উভয়ের জন্য মক অবজেক্ট তৈরি করতে সহায়ক। এটি বিভিন্ন ধরনের মকিং (full mock, partial mock) এর মাধ্যমে নির্ভরশীলতার আচরণকে নিয়ন্ত্রণ এবং যাচাই করার সুবিধা প্রদান করে। Interface Mocking সাধারণত কোডের নমনীয়তা এবং এক্সটেনসিবিলিটি বাড়াতে ব্যবহৃত হয়, যখন Class Mocking এ আপনি আসল ক্লাসের মেথডগুলির আচরণ পরিবর্তন করতে পারেন, যা টেস্টিংয়ের জন্য অত্যন্ত কার্যকরী।
EasyMock একটি শক্তিশালী mocking framework যা unit testing এর জন্য mock objects তৈরি করতে সাহায্য করে। যখন আপনার টেস্টে একাধিক অবজেক্টের ডিপেনডেন্সি থাকে, তখন EasyMock ব্যবহার করে আপনি সহজেই একাধিক mock তৈরি করতে এবং তাদেরকে পরিচালনা করতে পারেন। Multiple mocks তৈরি এবং ব্যবস্থাপনা করা টেস্টের কার্যকারিতা এবং পাঠযোগ্যতা বাড়ানোর জন্য গুরুত্বপূর্ণ।
এখানে, আমরা দেখব কীভাবে EasyMock ব্যবহার করে একাধিক mock অবজেক্ট তৈরি করা যায় এবং তাদের ব্যবস্থাপনা করা যায়।
Multiple Mocks তৈরি করার জন্য EasyMock ব্যবহার করা
ধরা যাক, আমাদের একটি OrderService ক্লাস রয়েছে, যা PaymentService এবং ShippingService এর উপর নির্ভরশীল। আমাদের OrderService এর কিছু মেথড টেস্ট করার জন্য PaymentService এবং ShippingService কে mock করতে হবে।
1. Interface and Class Definitions
// PaymentService interface
public interface PaymentService {
boolean processPayment(double amount);
}
// ShippingService interface
public interface ShippingService {
void shipOrder(String orderId);
}
// OrderService class which depends on PaymentService and ShippingService
public class OrderService {
private PaymentService paymentService;
private ShippingService shippingService;
public OrderService(PaymentService paymentService, ShippingService shippingService) {
this.paymentService = paymentService;
this.shippingService = shippingService;
}
public boolean placeOrder(String orderId, double amount) {
if (paymentService.processPayment(amount)) {
shippingService.shipOrder(orderId);
return true;
}
return false;
}
}
2. JUnit টেস্ট: Multiple Mocks তৈরি এবং ব্যবস্থাপনা
import static org.easymock.EasyMock.*;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class OrderServiceTest {
private PaymentService mockPaymentService;
private ShippingService mockShippingService;
private OrderService orderService;
@Before
public void setUp() {
// Creating multiple mocks
mockPaymentService = createMock(PaymentService.class);
mockShippingService = createMock(ShippingService.class);
// Creating the OrderService with mocked dependencies
orderService = new OrderService(mockPaymentService, mockShippingService);
}
@Test
public void testPlaceOrder_SuccessfulPayment() {
// Setting up the behavior of mocks
expect(mockPaymentService.processPayment(100.0)).andReturn(true);
mockShippingService.shipOrder("ORDER123");
// Activating mocks
replay(mockPaymentService, mockShippingService);
// Call the method to be tested
boolean result = orderService.placeOrder("ORDER123", 100.0);
// Assertions
assertTrue(result);
// Verify the behavior of mocks
verify(mockPaymentService, mockShippingService);
}
@Test
public void testPlaceOrder_FailedPayment() {
// Setting up the behavior of mocks
expect(mockPaymentService.processPayment(100.0)).andReturn(false);
// Activating mocks
replay(mockPaymentService, mockShippingService);
// Call the method to be tested
boolean result = orderService.placeOrder("ORDER123", 100.0);
// Assertions
assertFalse(result);
// Verify the behavior of mocks
verify(mockPaymentService, mockShippingService);
}
}
Explanation:
- Creating Multiple Mocks:
createMock()মেথড ব্যবহার করে আমরা দুইটি mock অবজেক্ট তৈরি করেছি:mockPaymentServiceএবংmockShippingService।- এই mocks গুলি আমাদের
OrderServiceএর constructor এ ইনজেক্ট করা হয়েছে।
- Setting Expectations:
expect()মেথড ব্যবহার করে আমরা mock objects-এর আচরণ নির্ধারণ করেছি। উদাহরণস্বরূপ, আমরাmockPaymentService.processPayment(100.0)এর জন্যtrueরিটার্ন আশা করছি, এবংmockShippingService.shipOrder("ORDER123")কল করার জন্য কোনো রিটার্ন আশা করছি না (void method)।
- Activating Mocks:
replay()মেথড ব্যবহার করে আমরা mocks-কে এক্টিভেট করেছি, যাতে তারা নির্ধারিত আচরণ অনুযায়ী কাজ করতে শুরু করে।
- Calling the Method:
orderService.placeOrder()মেথড কল করার পর, এটি mock objects এর মাধ্যমে ব্যবহৃত হবে এবং নির্ধারিত আচরণের উপর ভিত্তি করে কাজ করবে।
- Verifying Mocks:
verify()মেথড ব্যবহার করে আমরা নিশ্চিত করি যে mock objects তাদের নির্ধারিত আচরণ অনুযায়ী কাজ করেছে।
Multiple Mocks পরিচালনা করার কিছু গুরুত্বপূর্ণ পদ্ধতি:
- createMock(Class classToMock): এই মেথডটি নির্দিষ্ট ক্লাসের একটি mock অবজেক্ট তৈরি করে। একাধিক mock তৈরি করার জন্য আপনি একাধিক
createMock()কল করতে পারেন। - expect(): mock অবজেক্টের জন্য নির্দিষ্ট আচরণ সেট করে। একাধিক mock অবজেক্টের জন্য একাধিক
expect()ব্যবহার করা যেতে পারে। - replay(): এটি mock অবজেক্টগুলির আচরণ সক্রিয় করে। একাধিক mock অবজেক্টের জন্য একটি
replay()কল ব্যবহার করতে হবে। - verify(): এটি নিশ্চিত করে যে mock অবজেক্ট সঠিকভাবে ব্যবহার করা হয়েছে এবং প্রত্যাশিত আচরণ অনুসরণ করেছে। একাধিক mock অবজেক্টের জন্য
verify()কল ব্যবহার করা হয়।
ফলসী mock এবং স্টাব ব্যবহারের মধ্যে পার্থক্য:
- Mock Object: একটি mock object হল একটি object যার আচরণ সিমুলেট করা হয় এবং পরীক্ষার জন্য এর আচরণ নির্ধারণ করা হয়। আমরা verify() মেথড ব্যবহার করে নিশ্চিত করতে পারি যে এটি সঠিকভাবে কল হয়েছে।
- Stub Object: একটি stub object শুধুমাত্র নির্দিষ্ট ইনপুটের জন্য আউটপুট প্রদান করে, কিন্তু এটি পরীক্ষা করে না যে কতবার এটি কল হয়েছে। এটা মূলত পরীক্ষার জন্য নির্দিষ্ট আউটপুট বা ডেটা সরবরাহ করতে ব্যবহৃত হয়।
EasyMock এর মাধ্যমে Multiple Mocks তৈরি এবং ব্যবস্থাপনা করার সুবিধা
- Test Isolation: Multiple mocks ব্যবহারের মাধ্যমে আপনি একে অপরের থেকে স্বাধীনভাবে প্রতিটি কম্পোনেন্টের আচরণ টেস্ট করতে পারবেন, যার ফলে unit testing আরও নির্ভুল হয়।
- Cleaner and More Readable Code: Multiple mocks ব্যবহারের মাধ্যমে কোডে সরলতা আনা যায়, কারণ আপনি নির্দিষ্ট অবজেক্ট বা সার্ভিসের বাস্তবায়ন ছাড়াই শুধুমাত্র আচরণ কাস্টমাইজ করতে পারেন।
- Loosely Coupled Tests: মক অবজেক্টগুলির মাধ্যমে টেস্টগুলি কম প্যারে সম্পর্কযুক্ত হয়, যার ফলে কোড আরও নমনীয় এবং পরিবর্তনশীল হয়।
EasyMock এবং JUnit এর মাধ্যমে Multiple Mocks তৈরি এবং পরিচালনা করা অত্যন্ত কার্যকরী একটি পদ্ধতি, বিশেষ করে যখন একটি টেস্ট ক্লাসে অনেক ডিপেনডেন্সি বা অবজেক্ট থাকে। Mock objects ব্যবহার করে, আমরা বাইরের সিস্টেমের সাথে সরাসরি যোগাযোগ না করে, নির্দিষ্ট আচরণ সিমুলেট করতে পারি এবং সিস্টেমের প্রতিটি অংশ পরীক্ষা করতে পারি। এর মাধ্যমে টেস্টিং আরও সহজ, দ্রুত, এবং নির্ভুল হয়।
Read more