<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Mockito]]></title><description><![CDATA[Mockito]]></description><link>https://mockito.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 24 Sep 2026 08:51:54 GMT</lastBuildDate><atom:link href="https://mockito.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Mockito Saved My Tests: A Journey from Integration Nightmares to Unit Testing Bliss]]></title><description><![CDATA[Imagine testing a banking application where every test actually transfers real money. Sounds terrifying, right? That's exactly what happens when you test without mocking dependencies. Enter Mockito - the Java developer's best friend for creating 'fak...]]></description><link>https://mockito.hashnode.dev/how-mockito-saved-my-tests-a-journey-from-integration-nightmares-to-unit-testing-bliss</link><guid isPermaLink="true">https://mockito.hashnode.dev/how-mockito-saved-my-tests-a-journey-from-integration-nightmares-to-unit-testing-bliss</guid><category><![CDATA[qa testing]]></category><category><![CDATA[QA automation]]></category><category><![CDATA[Java]]></category><category><![CDATA[Testing]]></category><category><![CDATA[testing tool]]></category><category><![CDATA[mockito]]></category><category><![CDATA[Mocktest]]></category><dc:creator><![CDATA[Laiba Babar]]></dc:creator><pubDate>Tue, 09 Dec 2025 20:28:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765312040136/a8ce5474-53b9-42a5-aa7f-6f0f5239340a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine testing a banking application where every test actually transfers real money. Sounds terrifying, right? That's exactly what happens when you test without mocking dependencies. Enter Mockito - the Java developer's best friend for creating 'fake' objects that pretend to be databases, APIs, payment gateways, and more. In this comprehensive guide, we'll transform you from a Mockito newbie to a testing wizard. Whether you're tired of waiting for slow database calls or frustrated with flaky integration tests, you're about to discover how Mockito makes testing faster, more reliable, and actually enjoyable.</p>
<p>Note: See Maven dependencies at the end of article.</p>
<h3 id="heading-common-mockito-methods"><strong>Common Mockito Methods</strong></h3>
<h4 id="heading-1-creating-mocks"><strong>1. Creating Mocks</strong></h4>
<pre><code class="lang-plaintext">// Method 1: Using annotation (RECOMMENDED)
@Mock
BookRepository bookRepo;

// Method 2: Using mock() method
BookRepository bookRepo = mock(BookRepository.class);
</code></pre>
<h4 id="heading-2-stubbing-telling-mock-what-to-return"><strong>2. Stubbing (Telling mock what to return)</strong></h4>
<pre><code class="lang-plaintext">// Return specific value
when(bookRepo.findById(100L)).thenReturn(book);

// Return different values on multiple calls
when(bookRepo.findById(anyLong()))
    .thenReturn(book1)  // First call returns book1
    .thenReturn(book2); // Second call returns book2

// Throw exception
when(bookRepo.findById(999L)).thenThrow(new RuntimeException());

// Do nothing (for void methods)
doNothing().when(bookRepo).update(any(Book.class));
</code></pre>
<h4 id="heading-3-verification-checking-mock-was-used"><strong>3. Verification (Checking mock was used)</strong></h4>
<pre><code class="lang-plaintext">// Was called exactly once (default)
verify(bookRepo).findById(100L);

// Was called specific number of times
verify(bookRepo, times(2)).findById(100L); // Called twice
verify(bookRepo, atLeastOnce()).findById(100L); // At least once
verify(bookRepo, atMost(3)).findById(100L); // At most 3 times

// Was never called
verify(bookRepo, never()).findById(999L);

// Verify no more interactions
verifyNoMoreInteractions(bookRepo);
</code></pre>
<h2 id="heading-exercise-1-simple-calculator"><strong>Exercise 1: Simple Calculator</strong></h2>
<pre><code class="lang-plaintext">// CalculatorService.java

public class CalculatorService {
    private MathOperations mathOps;

    public CalculatorService(MathOperations mathOps) {
        this.mathOps = mathOps;
    }

    public double calculateAverage(int a, int b) {
        int sum = mathOps.add(a, b);
        return mathOps.divide(sum, 2);
    }
}
</code></pre>
<pre><code class="lang-plaintext">// // CalculatorServiceTest.java

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

@ExtendWith(MockitoExtension.class)
public class CalculatorServiceTest {

    @Mock
    private MathOperations mathOps;

    @Test
    public void testCalculateAverage() {
        // ARRANGE
        // Program the mock
        when(mathOps.add(10, 20)).thenReturn(30);
        when(mathOps.divide(30, 2)).thenReturn(15.0);

        CalculatorService calculator = new CalculatorService(mathOps);

        // ACT
        double result = calculator.calculateAverage(10, 20);

        // ASSERT
        assertEquals(15.0, result);

        // VERIFY
        verify(mathOps).add(10, 20);
        verify(mathOps).divide(30, 2);
    }
}
</code></pre>
<h2 id="heading-the-3-step-testing-pattern"><strong>The 3-Step Testing Pattern</strong></h2>
<p><strong>AAA Pattern</strong> - Arrange, Act, Assert</p>
<pre><code class="lang-plaintext">@Test
public void testMethod() {
    // 1. ARRANGE: Setup
    @Mock Dependency dependency;
    when(dependency.method()).thenReturn(value);
    Service service = new Service(dependency);

    // 2. ACT: Execute
    Result result = service.methodToTest();

    // 3. ASSERT &amp; VERIFY: Check
    assertEquals(expected, result);
    verify(dependency).method();
}
</code></pre>
<h2 id="heading-most-used-methods">Most Used Methods</h2>
<pre><code class="lang-plaintext">// CREATE
@Mock Dependency dep;                    // Create mock
Dependency dep = mock(Dependency.class); // Alternative

// STUB
when(dep.method()).thenReturn(value);    // Return value
when(dep.method()).thenThrow(exception); // Throw exception
doNothing().when(dep).voidMethod();      // Void method

// VERIFY
verify(dep).method();                    // Was called once
verify(dep, times(n)).method();          // Called n times
verify(dep, never()).method();           // Never called

// MATCHERS
any(), anyString(), anyInt()             // Match any argument
eq(value)                                // Match specific value
</code></pre>
<h2 id="heading-exercise-2-make-mockito-test">Exercise 2: Make Mockito Test</h2>
<pre><code class="lang-plaintext">public class UserService {
    private UserRepository userRepo;
    private EmailService emailService;

    public UserService(UserRepository repo, EmailService email) {
        this.userRepo = repo;
        this.emailService = email;
    }

    public boolean registerUser(String email, String name) {
        // Check if email exists
        if (userRepo.findByEmail(email) != null) {
            return false; // Email already registered
        }

        // Create new user
        User user = new User();
        user.setEmail(email);
        user.setName(name);

        // Save to database
        userRepo.save(user);

        // Send welcome email
        emailService.sendWelcomeEmail(email);

        return true;
    }
}
</code></pre>
<pre><code class="lang-plaintext">import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)  // This enables Mockito annotations
public class UserServiceTest {

    // Create MOCKS for dependencies
    @Mock
    private UserRepository userRepository;  // Fake database

    @Mock
    private EmailService emailService;      // Fake email service

    @Test
    public void testRegisterUser_Success() {
        // ========== 1. ARRANGE ==========
        // Setup the test scenario

        // Program the userRepository mock:
        // When findByEmail("test@example.com") is called, return null
        // (meaning email doesn't exist in database)
        when(userRepository.findByEmail("test@example.com"))
            .thenReturn(null);

        // Create the real UserService with our fake dependencies
        UserService userService = new UserService(userRepository, emailService);

        // ========== 2. ACT ==========
        // Call the method we're testing
        boolean result = userService.registerUser("test@example.com", "John Doe");

        // ========== 3. ASSERT ==========
        // Check the result
        assertTrue(result, "Registration should succeed");

        // ========== VERIFY ==========
        // Check that the mocks were used correctly

        // Verify userRepository.findByEmail was called with "test@example.com"
        verify(userRepository).findByEmail("test@example.com");

        // Verify userRepository.save was called with any User object
        verify(userRepository).save(any(User.class));

        // Verify emailService.sendWelcomeEmail was called with "test@example.com"
        verify(emailService).sendWelcomeEmail("test@example.com");
    }
}

// failure case
@Test
public void testRegisterUser_EmailAlreadyExists() {
    // ========== 1. ARRANGE ==========
    // Create an existing user
    User existingUser = new User();
    existingUser.setEmail("existing@example.com");
    existingUser.setName("Existing User");

    // Program the mock: When findByEmail is called with "existing@example.com",
    // return the existingUser (email already registered)
    when(userRepository.findByEmail("existing@example.com"))
        .thenReturn(existingUser);

    UserService userService = new UserService(userRepository, emailService);

    // ========== 2. ACT ==========
    boolean result = userService.registerUser("existing@example.com", "New User");

    // ========== 3. ASSERT ==========
    assertFalse(result, "Registration should fail when email exists");

    // ========== VERIFY ==========
    // Check findByEmail was called
    verify(userRepository).findByEmail("existing@example.com");

    // Check save was NEVER called (because registration failed)
    verify(userRepository, never()).save(any(User.class));

    // Check email was NEVER sent
    verify(emailService, never()).sendWelcomeEmail(anyString());
}
</code></pre>
<h2 id="heading-just-remember">Just Remember!!</h2>
<pre><code class="lang-plaintext">// 1. ARRANGE
when(mock.method()).thenReturn(value);

// 2. ACT 
result = service.methodUnderTest();

// 3. ASSERT &amp; VERIFY
assertEquals(expected, result);
verify(mock).method();
</code></pre>
<h1 id="heading-spy">SPY</h1>
<h3 id="heading-pattern-1-spy-with-real-object"><strong>Pattern 1: Spy with Real Object</strong></h3>
<pre><code class="lang-plaintext">// Create real object
RealClass realObj = new RealClass();

// Create spy
RealClass spy = spy(realObj);

// Mock SOME methods
doReturn("mocked").when(spy).someMethod();
</code></pre>
<h3 id="heading-pattern-2-spy-with-class"><strong>Pattern 2: Spy with Class</strong></h3>
<pre><code class="lang-plaintext">@Spy
NotificationService spyService; // Mockito creates instance

// OR
NotificationService spy = spy(NotificationService.class);
</code></pre>
<h2 id="heading-when-to-use-spy"><strong>When to Use SPY?</strong></h2>
<h3 id="heading-use-spy-when"><strong>Use SPY when:</strong></h3>
<ol>
<li><p><strong>Testing legacy code</strong> that you can't refactor</p>
</li>
<li><p><strong>Partially testing a class</strong> (some methods real, some mocked)</p>
</li>
<li><p><strong>Testing template method pattern</strong></p>
</li>
<li><p><strong>When object has complex initialization</strong></p>
</li>
</ol>
<h3 id="heading-use-mock-when"><strong>Use MOCK when:</strong></h3>
<ol>
<li><p><strong>Testing with dependencies</strong> (repositories, services)</p>
</li>
<li><p><strong>Complete isolation needed</strong></p>
</li>
<li><p><strong>Most common case - 90% of tests!</strong></p>
</li>
</ol>
<h2 id="heading-exercise-3-using-mock-injectmock-and-spy">Exercise 3: Using @mock, @injectMock and @spy</h2>
<pre><code class="lang-plaintext">public class LibraryManager {
    private BookRepository bookRepo;
    private UserRepository userRepo;
    private NotificationService notifier;

    // Constructor
    public LibraryManager(BookRepository bookRepo, UserRepository userRepo, 
                         NotificationService notifier) {
        this.bookRepo = bookRepo;
        this.userRepo = userRepo;
        this.notifier = notifier;
    }

    public void borrowBook(Long userId, Long bookId) {
        User user = userRepo.findById(userId);
        Book book = bookRepo.findById(bookId);

        if (user == null || book == null || !book.isAvailable()) {
            throw new IllegalArgumentException("Cannot borrow");
        }

        book.setAvailable(false);
        bookRepo.update(book);

        notifier.sendBorrowNotification(user.getEmail(), book.getTitle());
    }
}
</code></pre>
<pre><code class="lang-plaintext">@ExtendWith(MockitoExtension.class)
public class LibraryManagerTest {

    @Mock
    private BookRepository bookRepo;

    @Mock
    private UserRepository userRepo;

    @Spy  // We'll use partial mocking
    private NotificationService notifier;

    @InjectMocks
    private LibraryManager libraryManager;  // Auto-injected!

    @Test
    public void testBorrowBook_Success() {
        // ========== ARRANGE ==========
        User user = new User(1L, "john@example.com");
        Book book = new Book(100L, "Mockito Guide", true);

        when(userRepo.findById(1L)).thenReturn(user);
        when(bookRepo.findById(100L)).thenReturn(book);

        // Spy: Mock only sendBorrowNotification, keep rest real
        doNothing().when(notifier).sendBorrowNotification(anyString(), anyString());

        // ========== ACT ==========
        libraryManager.borrowBook(1L, 100L);

        // ========== VERIFY ==========
        verify(bookRepo).update(book);
        assertFalse(book.isAvailable());  // State changed
        verify(notifier).sendBorrowNotification("john@example.com", "Mockito Guide");
    }
}
</code></pre>
<h1 id="heading-argumentcaptor">ArgumentCaptor</h1>
<p>Problem:</p>
<pre><code class="lang-plaintext">// We can verify a method WAS called
verify(bookRepository).save(any(Book.class));

// But WHAT Book was saved? What data did it have?
// We can't check with just verify()!
</code></pre>
<p>Syntax:</p>
<pre><code class="lang-plaintext">// Step1: create the captor

// Syntax: ArgumentCaptor.forClass(ClassYouWantToCapture.class)
ArgumentCaptor&lt;User&gt; userCaptor = ArgumentCaptor.forClass(User.class);

// What this does:
// "Create a spy camera that captures User objects"
// It's EMPTY right now - hasn't captured anything yet

//Step2: Execute the code
userService.registerUser("John", "john@email.com", 25);

// What happens:
// 1. UserService creates a User object
// 2. UserService calls userRepo.save(user)
// 3. Our mock receives the User object

// Step3: Capture during verification
verify(userRepo).save(userCaptor.capture());

// What happens:
// 1. verify() checks save() was called
// 2. .capture() says: "Grab the argument that was passed"
// 3. The User object is stored inside userCaptor

// Step4: get and inspect
User capturedUser = userCaptor.getValue();

// Now capturedUser is THE ACTUAL User that was passed!
// We can check all its properties
</code></pre>
<h2 id="heading-scenario-shopping-cart-checkout"><strong>Scenario: Shopping Cart Checkout</strong></h2>
<pre><code class="lang-plaintext">public class ShoppingCart {
    private OrderRepository orderRepo;

    public void checkout(List&lt;Item&gt; items) {
        for (Item item : items) {
            Order order = createOrder(item);
            orderRepo.save(order);  // Called MULTIPLE times!
        }
    }
}
</code></pre>
<pre><code class="lang-plaintext">@Test
public void testMultipleCaptures() {
    // ========== 1. CREATE CAPTOR ==========
    ArgumentCaptor&lt;Order&gt; orderCaptor = ArgumentCaptor.forClass(Order.class);

    // ========== 2. SETUP ==========
    List&lt;Item&gt; items = Arrays.asList(
        new Item("Book", 20.0),
        new Item("Pen", 5.0),
        new Item("Notebook", 15.0)
    );

    // ========== 3. EXECUTE ==========
    shoppingCart.checkout(items);

    // ========== 4. CAPTURE ALL CALLS ==========
    // times(3) because save() will be called 3 times
    verify(orderRepo, times(3)).save(orderCaptor.capture());

    // ========== 5. GET ALL CAPTURED VALUES ==========
    List&lt;Order&gt; allCapturedOrders = orderCaptor.getAllValues();

    // ========== 6. INSPECT ALL ==========
    assertEquals(3, allCapturedOrders.size());

    // Check first order
    assertEquals("Book", allCapturedOrders.get(0).getItemName());
    assertEquals(20.0, allCapturedOrders.get(0).getPrice());

    // Check second order  
    assertEquals("Pen", allCapturedOrders.get(1).getItemName());

    // Check third order
    assertEquals("Notebook", allCapturedOrders.get(2).getItemName());
}
</code></pre>
<h1 id="heading-maven-dependencies">Maven Dependencies:</h1>
<pre><code class="lang-plaintext">&lt;!-- JUnit 5 --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;
    &lt;artifactId&gt;junit-jupiter&lt;/artifactId&gt;
    &lt;version&gt;5.8.2&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

&lt;!-- Mockito Core --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.mockito&lt;/groupId&gt;
    &lt;artifactId&gt;mockito-core&lt;/artifactId&gt;
    &lt;version&gt;3.12.4&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

&lt;!-- Mockito + JUnit 5 Integration --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.mockito&lt;/groupId&gt;
    &lt;artifactId&gt;mockito-junit-jupiter&lt;/artifactId&gt;
    &lt;version&gt;3.12.4&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre>
]]></content:encoded></item></channel></rss>