Skill

JUnit এবং Mocking Framework Integration

Java Technologies - জেইউনিট (JUnit)
156
156

JUnit হল একটি অত্যন্ত জনপ্রিয় টেস্টিং ফ্রেমওয়ার্ক যা Java প্রোগ্রামিং ভাষায় ইউনিট টেস্টিং করার জন্য ব্যবহৃত হয়। JUnit এর মাধ্যমে আপনি আপনার কোডের কার্যকারিতা পরীক্ষা করতে পারেন, এবং এটি ডেভেলপমেন্ট প্রক্রিয়াকে আরও নির্ভরযোগ্য এবং কার্যকরী করে তোলে। তবে, বাস্তব জীবনের বেশিরভাগ অ্যাপ্লিকেশনগুলো অনেক ধরনের এক্সটার্নাল ডিপেনডেন্সির উপর নির্ভরশীল থাকে, যেমন ডাটাবেস, API, ফাইল সিস্টেম ইত্যাদি। এই ডিপেনডেন্সিগুলি মক (mock) করতে হলে Mocking Framework ব্যবহার করা হয়।

JUnit এর সাথে Mocking Framework ইন্টিগ্রেশন করলে আপনি ডিপেনডেন্সি-অ্যাবস্ট্র্যাক্ট টেস্টগুলো সহজে তৈরি করতে পারেন এবং টেস্টগুলির নির্ভরযোগ্যতা আরও বাড়াতে পারেন। এখানে, আমরা JUnit এবং Mocking Framework (যেমন Mockito) এর ইন্টিগ্রেশন এবং এর ব্যবহার সম্পর্কে আলোচনা করব।


১. JUnit এবং Mocking Framework এর প্রয়োজনীয়তা

Mocking এর প্রয়োজনীয়তা:

  1. External Dependencies: বাস্তব লাইফের অ্যাপ্লিকেশনগুলিতে এক্সটার্নাল ডিপেনডেন্সি থাকে (যেমন ডাটাবেস, ওয়েব সার্ভিস ইত্যাদি)। এই ডিপেনডেন্সিগুলিকে এক্সিকিউট করার জন্য টেস্ট চালানোর সময় অনেকটা সময় এবং রিসোর্স খরচ হতে পারে। মকিং ফ্রেমওয়ার্ক ব্যবহার করলে আমরা এই ডিপেনডেন্সিগুলির কার্যকারিতা সিমুলেট করতে পারি।
  2. Isolated Testing: মকিং ফ্রেমওয়ার্কের মাধ্যমে আমরা শুধু নির্দিষ্ট কোডের অংশের পরীক্ষা করতে পারি, বাকি সিস্টেম থেকে আলাদা করে, যা আরও নিখুঁত এবং কার্যকরী টেস্টিং নিশ্চিত করে।
  3. Performance: এক্সটার্নাল ডিপেনডেন্সির কারণে পরীক্ষার সময় অনেকটা বৃদ্ধি পায়, মকিং ফ্রেমওয়ার্ক ব্যবহার করলে সময় এবং রিসোর্স সাশ্রয় করা সম্ভব।

২. JUnit এবং Mockito Integration

Mockito একটি জনপ্রিয় মকিং ফ্রেমওয়ার্ক যা JUnit এর সাথে একত্রে ব্যবহৃত হয়। এটি স্টাব (stub) বা মক অবজেক্ট তৈরি করে, যা আপনার টেস্টের জন্য প্রয়োজনীয় ডিপেনডেন্সির কার্যকারিতা সিমুলেট করে।

২.১ JUnit এবং Mockito সেটআপ

JUnit এবং Mockito কে একত্রে ব্যবহার করতে হলে আপনাকে JUnit এবং Mockito এর ডিপেনডেন্সি আপনার pom.xml (Maven) অথবা build.gradle (Gradle) ফাইলে যোগ করতে হবে।

Maven Dependency:

<dependencies>
    <!-- JUnit Dependency -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>

    <!-- Mockito Dependency -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.9.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Gradle Dependency:

dependencies {
    // JUnit Dependency
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'

    // Mockito Dependency
    testImplementation 'org.mockito:mockito-core:3.9.0'
}

২.২ Mockito Setup with JUnit 5 Example

Mockito এবং JUnit 5 একসাথে ব্যবহার করার জন্য @ExtendWith(MockitoExtension.class) অ্যানোটেশন ব্যবহার করা হয়। এই অ্যানোটেশনটি Mockito প্লাগইনকে সক্রিয় করে, যাতে আপনি mock অবজেক্ট তৈরি এবং ইনজেক্ট করতে পারেন।

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {

    @Mock
    private MyRepository myRepository;  // Mocked dependency

    @InjectMocks
    private MyService myService;  // The service class under test

    @Test
    void testServiceMethod() {
        // Arrange: Define behavior for the mocked repository
        when(myRepository.findData()).thenReturn("Mocked Data");

        // Act: Call the method we want to test
        String result = myService.getData();

        // Assert: Verify the expected behavior
        assertEquals("Mocked Data", result);
    }
}

এখানে:

  • @Mock: এই অ্যানোটেশনটি MyRepository এর একটি মক অবজেক্ট তৈরি করে।
  • @InjectMocks: এটি myService অবজেক্টে মক করা myRepository ইনজেক্ট করে।
  • when...thenReturn: এটি একটি মক করা মেথডের আচরণ নির্ধারণ করে।

৩. Mockito স্টাবিং এবং ভেরিফিকেশন

Mockito স্টাবিং এবং ভেরিফিকেশন দুইটি প্রধান ফিচার, যা আপনাকে টেস্টে মক অবজেক্টের আচরণ সঠিকভাবে পরীক্ষা করতে সহায়তা করে।

৩.১ Mockito স্টাবিং

স্টাবিং হল একটি মেথডের ফলাফল কাস্টমাইজ করা, যাতে আপনি মক অবজেক্টের আচরণ নির্ধারণ করতে পারেন।

// Stub the method to return specific value
when(myRepository.getUserName()).thenReturn("John");

এখানে, myRepository.getUserName() মেথডের জন্য আমরা "John" ফলাফলটি নির্ধারণ করেছি।

৩.২ Mockito ভেরিফিকেশন

ভেরিফিকেশন হল টেস্টের শেষে মক অবজেক্টের ব্যবহৃত মেথডগুলি পরীক্ষা করা।

// Verify if method was called once
verify(myRepository, times(1)).getUserName();

এটি নিশ্চিত করে যে getUserName() মেথডটি একবার ডাকা হয়েছে।


৪. Mockito Argument Capturing

Argument Capturing ব্যবহারের মাধ্যমে আপনি মক মেথডের প্যারামিটারগুলো ক্যাপচার করতে পারেন এবং সেগুলি যাচাই করতে পারেন।

ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(myRepository).saveData(captor.capture());

// Verify the captured argument
assertEquals("Test Data", captor.getValue());

এখানে, saveData মেথডের প্যারামিটার ক্যাপচার করা হয়েছে এবং সঠিকতার জন্য যাচাই করা হয়েছে।


৫. Mockito Exception Handling

Mockito এর মাধ্যমে আপনি মক মেথড থেকে এক্সসেপশন থ্রো করার আচরণও নির্ধারণ করতে পারেন।

when(myRepository.getUserName()).thenThrow(new RuntimeException("User not found"));

// Assert that the exception is thrown
assertThrows(RuntimeException.class, () -> myService.getData());

এখানে, getUserName মেথডটি একটি RuntimeException থ্রো করবে এবং আমরা সেটি যাচাই করছি।


৬. JUnit 5 এবং Mockito সহ উন্নত টেস্টিং

JUnit 5 এবং Mockito এর মধ্যে সিম্পল এবং কমপ্লেক্স টেস্টিং কৌশল ইন্টিগ্রেট করতে কিছু অতিরিক্ত ফিচার ব্যবহৃত হয়। এর মধ্যে রয়েছে:

  • @Mock, @InjectMocks, @Captor এবং @Spy অ্যানোটেশন ব্যবহার।
  • Mockito Argument Matchers: এটা দিয়ে আপনি প্যারামিটার ম্যাচিং করতে পারেন যেমন eq(), any(), isNull() ইত্যাদি।
when(myRepository.save(any(User.class))).thenReturn(true);

এখানে, any(User.class) এর মাধ্যমে User অবজেক্টের যেকোনো ইনস্ট্যান্সকে গ্রহণ করা হবে।


সারাংশ

JUnit এবং Mockito এর ইন্টিগ্রেশন Java এ ইউনিট টেস্টিংয়ের জন্য অত্যন্ত কার্যকরী। Mockito মকিং ফ্রেমওয়ার্ক ব্যবহার করে আপনি JUnit টেস্টগুলিকে আরও উন্নত এবং নির্ভরযোগ্য করতে পারেন, যেখানে এক্সটার্নাল ডিপেনডেন্সিগুলির কার্যকারিতা সিমুলেট করতে সক্ষম হন। এটি কাস্টম স্টাবিং, ভেরিফিকেশন, এক্সসেপশন হ্যান্ডলিং, এবং আর্গুমেন্ট ক্যাপচারিং এর মাধ্যমে আপনার টেস্টিং প্রক্রিয়া আরো নিখুঁত করে তোলে।


Content added By

Mocking কি এবং কখন প্রয়োজন?

107
107

Mocking একটি প্রক্রিয়া যেখানে আপনি একটি অবজেক্টের mock সংস্করণ তৈরি করেন, যাতে প্রকৃত অবজেক্টের আচরণ বা ডেটার উপর নির্ভর না করে, আপনি শুধু নির্দিষ্ট মেথডগুলো পরীক্ষা করতে পারেন। এটি সাধারণত unit testing এ ব্যবহৃত হয়, বিশেষত যখন আপনি এমন একটি কোড টেস্ট করছেন যা বহিরাগত সিস্টেমের উপর নির্ভরশীল (যেমন ডাটাবেস, ওয়েব সার্ভিস, বা ফাইল সিস্টেম)।

JUnit টেস্টিংয়ে Mocking ব্যবহারের মাধ্যমে আপনি সহজেই নির্দিষ্ট ফাংশনালিটি বা কোডের অংশ পরীক্ষা করতে পারেন, যেমন ডিপেনডেন্সি ইনজেকশন ব্যবহার করে।


১. Mocking এর প্রয়োজনীয়তা

প্রকৃত অবজেক্টগুলি এক্সটার্নাল সার্ভিস (ডাটাবেস, API কল, ইত্যাদি) বা সিস্টেমের উপর নির্ভরশীল হলে, তাদেরকে সরাসরি টেস্ট করা খুবই সময়সাপেক্ষ এবং কঠিন হতে পারে। এরকম পরিস্থিতিতে Mocking খুবই গুরুত্বপূর্ণ কারণ:

  • Speed: বাহ্যিক সিস্টেমের সাথে যোগাযোগের পরিবর্তে, আপনি মক অবজেক্ট ব্যবহার করে দ্রুত টেস্ট করতে পারেন।
  • Isolation: কোডের নির্দিষ্ট অংশকে একা পরীক্ষা করতে সক্ষম হন, বাহ্যিক ডিপেনডেন্সি থেকে বিচ্ছিন্ন হয়ে।
  • Control: মক অবজেক্টের মাধ্যমে আপনি কাস্টম আউটপুট নির্ধারণ করতে পারেন এবং এর মাধ্যমে কোডের আচরণ পরীক্ষা করতে পারেন।

২. Mocking কিভাবে কাজ করে?

Mocking একটি উপাদান বা অবজেক্টের আচরণ কৃত্রিমভাবে তৈরি করা। সাধারণত, Mockito বা EasyMock এর মতো লাইব্রেরি ব্যবহার করে Mocking করা হয়। এই লাইব্রেরিগুলি আপনাকে মক অবজেক্ট তৈরি এবং তাদের আচরণ কনফিগার করতে সহায়তা করে।

উদাহরণ:

ধরা যাক, আপনার একটি ক্লাস আছে যা ডাটাবেসে ডাটা সেভ করার জন্য একটি DatabaseService ব্যবহার করে। আপনি যদি DatabaseService টেস্ট করতে চান, তবে আপনাকে আসল ডাটাবেসে সংযোগ স্থাপন করতে হবে, যা অপ্রয়োজনীয় এবং সময়সাপেক্ষ হতে পারে। এখানে Mocking ব্যবহার করে আপনি একটি মক ডাটাবেস অবজেক্ট তৈরি করতে পারেন।

DatabaseService ক্লাস:
public class DatabaseService {
    private Database database;

    public DatabaseService(Database database) {
        this.database = database;
    }

    public boolean saveData(String data) {
        // Data is saved in the database
        return database.save(data);
    }
}
Database ক্লাস:
public class Database {
    public boolean save(String data) {
        // Actual logic to save data in a real database
        return true;
    }
}

এখন, JUnit টেস্টের জন্য Mocking ব্যবহার করা হবে যাতে ডাটাবেসের আসল কোড চালানো না হয়।

DatabaseServiceTest (Mocking Example):
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class DatabaseServiceTest {

    @Test
    public void testSaveData() {
        // Create a mock of the Database class
        Database mockDatabase = mock(Database.class);

        // Define the behavior of the mock object
        when(mockDatabase.save("Test Data")).thenReturn(true);

        // Create the service with the mock object
        DatabaseService databaseService = new DatabaseService(mockDatabase);

        // Perform the test
        boolean result = databaseService.saveData("Test Data");

        // Verify the result
        assertTrue(result);
    }
}

এখানে:

  • mock(Database.class): Database ক্লাসের একটি মক অবজেক্ট তৈরি করা হয়েছে।
  • when(mockDatabase.save("Test Data")).thenReturn(true): মক অবজেক্টের save() মেথডকে কনফিগার করা হয়েছে যাতে এটি true রিটার্ন করে যখন "Test Data" পাস করা হয়।
  • assertTrue(result): নিশ্চিত করা হয়েছে যে saveData() মেথড সত্যি রিটার্ন করে, যেহেতু মক ডাটাবেসের save() মেথডটি true রিটার্ন করছে।

৩. Mocking ব্যবহার করার সময় কিছু টিপস

  1. Dependencies Mocking: যদি আপনার কোডের অন্য কোনো অংশ ডিপেনডেন্সি হিসেবে অন্য ক্লাস ব্যবহার করে, সেগুলোর মক অবজেক্ট তৈরি করুন। যেমন: API কল, ডাটাবেস, বা ফাইল সিস্টেম।
  2. Behavior Definition: মক অবজেক্টের আচরণ পরিষ্কারভাবে নির্ধারণ করুন। when(...).thenReturn(...) ব্যবহার করে মক অবজেক্টের প্রত্যাশিত ফলাফল সেট করুন।
  3. Interaction Verification: মক অবজেক্টের সাথে ইন্টারঅ্যাকশন কেমন হচ্ছে তা যাচাই করতে verify() মেথড ব্যবহার করুন।

    উদাহরণ:

    verify(mockDatabase).save("Test Data");
    
  4. Use Stubbing for Return Values: মক অবজেক্ট থেকে রিটার্নের জন্য ডিফল্ট বা কাস্টম মান ব্যবহার করুন।

    when(mockDatabase.save("Test Data")).thenReturn(false);  // Custom value
    
  5. Limitations: Mocking শুধুমাত্র তখনই ব্যবহার করুন যখন বাহ্যিক ডিপেনডেন্সি টেস্টের জন্য প্রয়োজনীয় না হয়। Mocking ব্যবহার করা বেশি হলে কোডের জটিলতা বেড়ে যেতে পারে।

৪. Mocking এর সুবিধা

  • Isolated Testing: মক অবজেক্ট ব্যবহার করে আপনি আপনার টেস্টের জন্য বাইরের সিস্টেমের উপর নির্ভরশীল না হয়ে কোডের নির্দিষ্ট অংশ পরীক্ষা করতে পারেন।
  • Increased Speed: বাহ্যিক সিস্টেমে ডেটা পাঠানো বা প্রাপ্ত করার পরিবর্তে, মক অবজেক্ট ব্যবহার করলে টেস্ট দ্রুত সম্পন্ন হয়।
  • Error Isolation: মক অবজেক্টের মাধ্যমে আপনি সহজে ডিপেনডেন্সি বা কোডের সমস্যাগুলি চিহ্নিত করতে পারেন।

৫. Mocking কখন প্রয়োজন?

Mocking তখন প্রয়োজনীয় হয়ে ওঠে যখন:

  1. আপনি বাহ্যিক সিস্টেমের উপর নির্ভরশীল কোড টেস্ট করছেন, যেমন ডাটাবেস, রিমোট সার্ভিস, ফাইল সিস্টেম ইত্যাদি।
  2. আপনি একটি নির্দিষ্ট কোড ফ্লো বা লজিক পরীক্ষা করতে চান এবং বাহ্যিক সিস্টেমের আচরণ আপনার পরীক্ষার সাথে প্রভাবিত না হোক তা নিশ্চিত করতে চান।
  3. বাহ্যিক সিস্টেমের কার্যক্রম ধীরগতির কারণে, আপনার টেস্ট আরও দ্রুত করতে চান।

উপসংহার

Mocking একটি গুরুত্বপূর্ণ টুল যা আপনাকে unit testing এর সময় বাহ্যিক ডিপেনডেন্সি থেকে বিচ্ছিন্ন হয়ে শুধুমাত্র কোডের নির্দিষ্ট অংশ পরীক্ষা করতে সাহায্য করে। এটি দ্রুত টেস্টিং, নির্ভরযোগ্যতা এবং সিস্টেমের পারফরম্যান্সে কোনো প্রভাব না ফেলতে ব্যবহৃত হয়। JUnit টেস্টিংয়ে Mockito ব্যবহার করে আপনি Mocking প্রক্রিয়া খুব সহজে এবং কার্যকরীভাবে বাস্তবায়ন করতে পারেন।


Content added By

Mockito এর সাথে JUnit Integration

91
91

JUnit এবং Mockito দুটি অত্যন্ত জনপ্রিয় টেস্টিং ফ্রেমওয়ার্ক যা Java এ ইউনিট টেস্ট লেখার জন্য ব্যবহৃত হয়। JUnit একটি টেস্ট ফ্রেমওয়ার্ক যা টেস্ট কেসের জন্য ব্যবহৃত হয়, আর Mockito একটি মকিং ফ্রেমওয়ার্ক যা সিস্টেমের আউটপুট পরীক্ষার জন্য মক (mock) অবজেক্ট তৈরি করতে সাহায্য করে।

Mockito ব্যবহার করে, আমরা JUnit টেস্টিংয়ে ডিপেনডেন্সি ইনজেকশন এবং মক অবজেক্ট তৈরি করতে পারি, যা টেস্টগুলোকে আরও কার্যকর এবং নির্ভুল করে তোলে। এই টিউটোরিয়ালে, আমরা JUnit এবং Mockito এর সমন্বয়ে টেস্ট লেখার প্রক্রিয়া আলোচনা করব।


১. JUnit এবং Mockito ব্যবহার করার জন্য ডিপেনডেন্সি

JUnit এবং Mockito ব্যবহার করতে হলে আপনাকে আপনার প্রোজেক্টে তাদের ডিপেনডেন্সি যোগ করতে হবে। Maven বা Gradle উভয় প্ল্যাটফর্মেই এটি করা যায়।

Maven Dependency:

<dependencies>
    <!-- JUnit Dependency -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Mockito Dependency -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.7.7</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Gradle Dependency:

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testImplementation 'org.mockito:mockito-core:3.7.7'
}

২. Mockito এবং JUnit এর মধ্যে সম্পর্ক

Mockito ফ্রেমওয়ার্কটি মূলত JUnit টেস্টিংয়ে মক অবজেক্ট তৈরি করতে ব্যবহৃত হয়, যাতে আপনি সিস্টেমের নির্দিষ্ট অংশগুলো টেস্ট করতে পারেন। মক অবজেক্টের মাধ্যমে আপনি আসল অবজেক্টের আচরণ চেক করতে পারেন, এবং টেস্টের পরিবেশকে নিয়ন্ত্রণ করতে পারেন।

Mockito JUnit এর সাথে একত্রে কাজ করতে পারে এবং JUnit 5 এর সাথে MockitoExtension ব্যবহার করে মকিং টেস্টে অ্যাসিস্ট করতে পারে।


৩. Mockito এর সাথে JUnit 5 Integration

JUnit 5 এর সাথে Mockito ব্যবহার করার জন্য, আপনি @ExtendWith(MockitoExtension.class) অ্যানোটেশন ব্যবহার করতে পারেন। এটি Mockito এর টেস্টিং ফিচারগুলোকে JUnit টেস্টে এক্সটেন্ড করে।

উদাহরণ: Mockito এর সাথে JUnit 5 Integration

ExampleService.java:

public class ExampleService {
    private final Dependency dependency;

    public ExampleService(Dependency dependency) {
        this.dependency = dependency;
    }

    public String processData() {
        return "Processed: " + dependency.getData();
    }
}

Dependency.java:

public class Dependency {
    public String getData() {
        return "Real Data";
    }
}

ExampleServiceTest.java:

import static org.mockito.Mockito.*;
import org.junit.jupiter.api.*;
import org.mockito.*;

public class ExampleServiceTest {

    @Mock
    private Dependency dependency;  // Mock object of Dependency

    private ExampleService exampleService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);  // Initialize mocks
        exampleService = new ExampleService(dependency);  // Inject mock into service
    }

    @Test
    void testProcessData() {
        // Arrange
        when(dependency.getData()).thenReturn("Mocked Data");  // Mock the behavior

        // Act
        String result = exampleService.processData();  // Call the method

        // Assert
        Assertions.assertEquals("Processed: Mocked Data", result);  // Assert the result
    }
}

ব্যাখ্যা:

  • @Mock অ্যানোটেশন ব্যবহার করে Dependency অবজেক্টটিকে মক করা হয়েছে।
  • MockitoAnnotations.openMocks(this) ব্যবহার করে Mockito অ্যানোটেশনকে ইনিশিয়ালাইজ করা হয়েছে।
  • when(dependency.getData()).thenReturn("Mocked Data") মক অবজেক্টের আচরণ কাস্টমাইজ করা হয়েছে।
  • assertEquals ব্যবহার করে রিটার্ন ভ্যালুর সাথে আসল আউটপুট যাচাই করা হয়েছে।

৪. Mockito এর সাহায্যে মকিং এর বিভিন্ন ধরন

৪.১ Mocking Void Methods

Mockito এর মাধ্যমে void মেথডগুলোও মক করা যায়। উদাহরণস্বরূপ, যদি কোনো মেথড কিছু রিটার্ন না করে (void), আপনি তখন doNothing() ব্যবহার করে তার আচরণ মক করতে পারবেন।

@Test
void testVoidMethod() {
    // Arrange
    doNothing().when(dependency).someVoidMethod();

    // Act
    exampleService.callVoidMethod();

    // Assert
    verify(dependency, times(1)).someVoidMethod();  // Verifying void method call
}

৪.২ Mocking with Argument Matchers

Mockito আপনাকে Argument Matchers ব্যবহার করতে দেয়, যা মেথড কলের আর্গুমেন্টের ভিত্তিতে মক আচরণ পরিবর্তন করতে সহায়তা করে।

@Test
void testWithArgumentMatchers() {
    when(dependency.getData(anyString())).thenReturn("Mocked Data");

    String result = exampleService.processData("Test");

    Assertions.assertEquals("Processed: Mocked Data", result);
}

এখানে, anyString() ব্যবহৃত হয়েছে যাতে কোনো স্ট্রিং প্যারামিটার গ্রহণ করা যায়।


৫. Mockito এর সাথে Verification

Mockito ব্যবহার করে আপনি মেথড কলের সংখ্যা এবং তাদের আচরণ যাচাই করতে পারেন। এটি একটি শক্তিশালী বৈশিষ্ট্য, যেটি নিশ্চিত করে যে সিস্টেমের কোন মেথডটি কল হয়েছে কিনা এবং কতবার।

উদাহরণ: Verifying Method Calls

@Test
void testMethodCall() {
    exampleService.processData();
    
    // Verify that the method was called once
    verify(dependency, times(1)).getData();
}

এখানে, verify ব্যবহার করে আপনি নিশ্চিত হচ্ছেন যে getData() মেথডটি শুধুমাত্র একবারই কল হয়েছে।


সারাংশ

JUnit এবং Mockito এর ইন্টিগ্রেশন আপনাকে সিস্টেমের আউটপুট এবং প্রেক্ষাপট অনুযায়ী টেস্ট কেস লিখতে সাহায্য করে। Mockito মকিং টেকনিক দ্বারা, আপনি সহজেই অপ্রয়োজনীয় বা বহিরাগত সিস্টেমের ডিপেনডেন্সি মক করতে পারেন এবং একে সহজেই JUnit টেস্ট কেসের মধ্যে ব্যবহার করতে পারেন। এর ফলে, টেস্টিংয়ের সময় আপনি ডেটা বা আচরণ কাস্টমাইজ করতে সক্ষম হবেন এবং আপনার টেস্টগুলো আরও নির্ভুলভাবে কাজ করবে।


Content added By

@Mock, @InjectMocks, এবং @Spy এর ব্যবহার

84
84

JUnit হল একটি জনপ্রিয় টেস্টিং ফ্রেমওয়ার্ক যা Java প্রোগ্রামিং ভাষায় ইউনিট টেস্টিং করতে ব্যবহৃত হয়। JUnit টেস্টিংয়ে Mockito লাইব্রেরি ব্যবহার করা হয় মকিং (Mocking) এবং স্পাইং (Spying) করার জন্য, যা টেস্টিংয়ের সময় নির্দিষ্ট উপাদানগুলোর আচরণ নিয়ন্ত্রণ করতে সহায়তা করে। Mockito এর মাধ্যমে @Mock, @InjectMocks, এবং @Spy অ্যানোটেশন ব্যবহার করে কোডের নির্দিষ্ট অংশের মক এবং স্পাই তৈরি করা যায়।

এই টিউটোরিয়ালে আমরা @Mock, @InjectMocks, এবং @Spy এর ব্যবহার এবং তাদের প্রয়োজনীয়তা সম্পর্কে আলোচনা করব।


১. @Mock এর ব্যবহার

@Mock অ্যানোটেশনটি ব্যবহৃত হয় একটি মক অবজেক্ট তৈরি করতে, যা একটি আসল অবজেক্টের আচরণ নকল করে। এটি টেস্টিংয়ের সময় কোনো নির্দিষ্ট কম্পোনেন্টের বাস্তব আচরণ বা এক্সটার্নাল সিস্টেম কল এড়াতে সাহায্য করে, এবং আপনি এই মক অবজেক্টের উপর পরীক্ষা চালাতে পারেন।

উদাহরণ:

ধরা যাক, আপনার একটি UserService ক্লাস আছে এবং এটি UserRepository কে ব্যবহার করে ডেটা রিট্রিভ করার জন্য।

public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(int id) {
        return userRepository.findById(id);
    }
}

এখন, UserRepository ক্লাসের জন্য @Mock ব্যবহার করা যেতে পারে:

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class UserServiceTest {

    @Mock
    private UserRepository userRepository; // Mock object

    @Test
    public void testGetUserById() {
        UserService userService = new UserService(userRepository);
        User user = new User(1, "John Doe");

        when(userRepository.findById(1)).thenReturn(user);  // Mock behavior

        User result = userService.getUserById(1);
        assertEquals("John Doe", result.getName());  // Verify the result
    }
}

এখানে @Mock ব্যবহার করে UserRepository মক করা হয়েছে, এবং আমরা মক অবজেক্টের উপর টেস্টিং করছি।


২. @InjectMocks এর ব্যবহার

@InjectMocks অ্যানোটেশনটি ব্যবহৃত হয়, মক অবজেক্টগুলিকে টেস্ট অবজেক্টে ইনজেক্ট করতে। এটি সেই ক্লাসটিতে ইনজেক্ট করে যা @Mock এর মাধ্যমে মক করা ডিপেনডেন্সি ব্যবহার করে।

উদাহরণ:

public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(int id) {
        return userRepository.findById(id);
    }
}

এখানে, @InjectMocks ব্যবহার করে UserService ক্লাসে UserRepository মক অবজেক্ট ইনজেক্ট করা যাবে:

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class UserServiceTest {

    @Mock
    private UserRepository userRepository; // Mock object

    @InjectMocks
    private UserService userService; // Inject mocks into UserService

    @Test
    public void testGetUserById() {
        User user = new User(1, "John Doe");

        when(userRepository.findById(1)).thenReturn(user);  // Mock behavior

        User result = userService.getUserById(1);
        assertEquals("John Doe", result.getName());  // Verify the result
    }
}

এখানে @InjectMocks ব্যবহার করে UserService ক্লাসে UserRepository মক অবজেক্ট ইনজেক্ট করা হয়েছে। এখন, UserService এর মেথডগুলি userRepository এর মক ডেটার সাথে পরীক্ষা করা যাবে।


৩. @Spy এর ব্যবহার

@Spy অ্যানোটেশনটি ব্যবহৃত হয় আসল অবজেক্টের উপর স্পাই তৈরি করতে, যার মাধ্যমে আপনি নির্দিষ্ট মেথডগুলিকে মক করতে পারেন, তবে অন্যান্য মেথডগুলো আসল আচরণ অনুসরণ করবে। এটি মূলত মক এবং আসল অবজেক্টের মিশ্রণ হিসেবে কাজ করে।

উদাহরণ:

ধরা যাক, আপনার একটি OrderService ক্লাস রয়েছে যা অর্ডার প্রসেসিংয়ের জন্য OrderRepository ব্যবহার করে।

public class OrderService {
    private OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public String processOrder(int orderId) {
        Order order = orderRepository.findOrderById(orderId);
        // Process order
        return "Order processed: " + order.getId();
    }
}

এখন, @Spy ব্যবহার করে আমরা আসল OrderService এর কিছু মেথড স্পাই করতে পারি:

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class OrderServiceTest {

    @Spy
    private OrderRepository orderRepository = new OrderRepository(); // Spy object

    @InjectMocks
    private OrderService orderService; // Inject mocks into OrderService

    @Test
    public void testProcessOrder() {
        Order order = new Order(1, "Laptop");
        when(orderRepository.findOrderById(1)).thenReturn(order);  // Mock behavior for spy

        String result = orderService.processOrder(1);
        assertEquals("Order processed: 1", result);  // Verify the result
    }
}

এখানে, @Spy ব্যবহার করে OrderRepository এর আসল অবজেক্টের ওপর কিছু মেথডের আচরণ নিয়ন্ত্রণ করা হয়েছে, এবং @InjectMocks এর মাধ্যমে মক অবজেক্ট OrderService এ ইনজেক্ট করা হয়েছে।


সারাংশ

  • @Mock: এটি একটি মক অবজেক্ট তৈরি করে যা আসল অবজেক্টের আচরণ নকল করে। এটি সাধারণত ডিপেনডেন্সি মকিংয়ের জন্য ব্যবহৃত হয়।
  • @InjectMocks: এটি মক অবজেক্টগুলিকে টেস্ট অবজেক্টে ইনজেক্ট করে।
  • @Spy: এটি আসল অবজেক্টের ওপর স্পাই তৈরি করে, এবং আপনি নির্দিষ্ট মেথডগুলিকে মক করতে পারেন, তবে অন্য মেথডগুলি আসল আচরণ অনুসরণ করবে।

এই অ্যানোটেশনগুলো JUnit টেস্টিংয়ে মকিং এবং স্পাইংকে সহজ ও কার্যকরী করে তোলে, যা টেস্টিং প্রক্রিয়াকে আরও নির্ভুল এবং দ্রুত করে তোলে।

Content added By

Practical উদাহরণ: Mockito এবং JUnit দিয়ে Service Layer Test করা

88
88

JUnit হল একটি জনপ্রিয় টেস্টিং ফ্রেমওয়ার্ক যা Java প্রোগ্রামে ইউনিট টেস্টিং সহজ করে তোলে। এটি বিশেষ করে ডেভেলপারদের জন্য গুরুত্বপূর্ণ, কারণ এটি কোডের বিভিন্ন ইউনিট বা মেথডের সঠিকতা যাচাই করতে সহায়তা করে। অন্যদিকে, Mockito হল একটি মকিং ফ্রেমওয়ার্ক যা JUnit টেস্টিংয়ের জন্য মক অবজেক্ট তৈরি করতে ব্যবহৃত হয়, যখন আপনি ডিপেনডেন্সি ইনজেকশন বা কোনো এক্সটার্নাল সিস্টেমকে মক করতে চান।

এই টিউটোরিয়ালে, আমরা Mockito এবং JUnit দিয়ে Service Layer এর টেস্টিং দেখব। Service Layer সাধারণত ব্যবসায়িক লজিক ধারণ করে এবং ডাটাবেসের সাথে যোগাযোগ করতে পারে, তবে আমরা এখানে মকিংয়ের মাধ্যমে টেস্ট করব।


১. JUnit এবং Mockito Setup

প্রথমে আপনাকে JUnit এবং Mockito এর ডিপেনডেন্সি আপনার pom.xml (Maven) বা build.gradle (Gradle) ফাইলে যোগ করতে হবে।

Maven Dependency (pom.xml)

<dependencies>
    <!-- JUnit Dependency -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Mockito Dependency -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>3.7.7</version>
        <scope>test</scope>
    </dependency>

    <!-- JUnit Vintage Engine for JUnit 4 tests -->
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>5.7.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Gradle Dependency (build.gradle)

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testImplementation 'org.mockito:mockito-core:3.7.7'
    testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.0'
}

২. Service Layer Test করার জন্য প্রয়োজনীয় ক্লাস

ধরা যাক, আমাদের একটি UserService ক্লাস রয়েছে যা UserRepository এর মাধ্যমে ডাটাবেসে User অবজেক্ট সংরক্ষণ ও রিটার্ন করে।

User.java (Model)

public class User {
    private String name;
    private int age;

    // Constructor, Getters and Setters
}

UserRepository.java (Repository Interface)

public interface UserRepository {
    User save(User user);
}

UserService.java (Service Layer)

public class UserService {

    private UserRepository userRepository;

    // Constructor injection
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User createUser(String name, int age) {
        User user = new User(name, age);
        return userRepository.save(user);
    }
}

এখানে, UserService ক্লাসে createUser মেথডটি UserRepository এর save মেথড ব্যবহার করে ডাটাবেসে একটি নতুন ব্যবহারকারী তৈরি করে।


৩. Mockito এবং JUnit দিয়ে Service Layer Test করা

এখন আমরা Mockito ব্যবহার করে UserRepository এর মক অবজেক্ট তৈরি করব এবং UserService এর createUser মেথডটিকে টেস্ট করব।

UserServiceTest.java (JUnit Test)

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class UserServiceTest {

    @Mock
    private UserRepository userRepository; // Mocking the UserRepository

    @InjectMocks
    private UserService userService; // Injecting the mocked repository into the service

    @BeforeEach
    public void setup() {
        MockitoAnnotations.openMocks(this); // Initialize the mock objects
    }

    @Test
    public void testCreateUser() {
        // Arrange
        User user = new User("John", 25);
        when(userRepository.save(any(User.class))).thenReturn(user); // Mocking the save method

        // Act
        User createdUser = userService.createUser("John", 25);

        // Assert
        assertNotNull(createdUser);
        assertEquals("John", createdUser.getName());
        assertEquals(25, createdUser.getAge());
        verify(userRepository, times(1)).save(any(User.class)); // Verifying that save was called once
    }
}

Explanation:

  • @Mock: Mockito ব্যবহার করে UserRepository এর মক অবজেক্ট তৈরি করা হয়েছে।
  • @InjectMocks: UserServiceUserRepository এর মক অবজেক্ট ইনজেক্ট করা হয়েছে।
  • MockitoAnnotations.openMocks(this): মক অবজেক্ট ইনিশিয়ালাইজ করতে ব্যবহৃত হয়।
  • when(userRepository.save(any(User.class))).thenReturn(user): আমরা save মেথডকে মক করছি যাতে এটি একটি নির্দিষ্ট ইউজার অবজেক্ট রিটার্ন করে।
  • assertNotNull(createdUser): পরীক্ষার উদ্দেশ্যে যাচাই করা হয়েছে যে, createdUser অবজেক্টটি null নয়।
  • verify(userRepository, times(1)).save(any(User.class)): নিশ্চিত করা হচ্ছে যে save মেথডটি একবারই কল হয়েছে।

৪. Mockito ব্যবহার করার সুবিধা

  • Unit Isolation: Mockito দিয়ে আপনি কোনো নির্ভরশীলতার উপর নির্ভর না করে শুধুমাত্র আপনার কোডের মূল অংশটিকে টেস্ট করতে পারেন। যেমন, ডাটাবেস বা রিমোট সার্ভিস মক করে এটি করা হয়।
  • Behavior Verification: Mockito দিয়ে আপনি মেথড কলের আচরণ পরীক্ষা করতে পারেন (যেমন, কতবার কোনো মেথড কল করা হয়েছে)।
  • No External Dependencies: প্রকৃত ডাটাবেস বা অন্য সিস্টেমের সাথে ইন্টিগ্রেশন ছাড়াই টেস্ট করা যায়, ফলে টেস্টিং দ্রুত এবং নির্ভরযোগ্য হয়।

সারাংশ

এই উদাহরণে, আমরা Mockito এবং JUnit ব্যবহার করে Service Layer এর টেস্টিং করেছি। Mockito এর সাহায্যে আমরা UserRepository এর মক অবজেক্ট তৈরি করেছি এবং UserService এর createUser মেথডটিকে টেস্ট করেছি। এটি একটি বাস্তব জীবনের উদাহরণ যেখানে Service Layer টেস্টিং এবং মকিংয়ের মাধ্যমে ডিপেনডেন্সি ইনজেকশন সহজভাবে সম্পন্ন করা হয়েছে।

Mockito এবং JUnit এর সাহায্যে ইউনিট টেস্টিং আরও সহজ, দ্রুত এবং নির্ভরযোগ্য হয়ে ওঠে, এবং এটি উন্নত সফটওয়্যার ডেভেলপমেন্ট প্রক্রিয়ার একটি অপরিহার্য অংশ।


Content added By
Promotion