Mocking and stubbing in Java unit testing

In unit testing, mocking and stubbing are crucial techniques for isolating code under test and creating controlled testing scenarios. These techniques allow developers to simulate interactions with external dependencies and replace certain behaviors during the testing process. In this blog post, we will explore mocking and stubbing in the context of Java unit testing and understand how they can improve the quality and efficiency of our tests.

What is Mocking?

Mocking is the process of creating a fake object that mimics the behavior of a real object or dependency. It allows us to define the responses and behaviors of the mocked object according to our test requirements. Mocking is particularly useful when testing code that depends on external dependencies such as databases, web services, or third-party APIs.

A popular Java mocking framework is Mockito, which provides a rich set of APIs for creating and working with mock objects. Let’s take a look at an example:

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.when;

public class MyUnitTest {

    @Mock
    private MyDependency myDependency;

    @BeforeEach
    public void setup() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testMyMethod() {
        when(myDependency.someMethod()).thenReturn("mocked response");

        // Test code that interacts with myDependency

        // Assertions and verifications
    }
}

In this example, MyDependency is a class that our code under test depends on. By annotating the myDependency field with @Mock, we create a mock object for it. In the testMyMethod() method, we use the when() method from Mockito’s API to define the behavior of myDependency when its someMethod() is called.

What is Stubbing?

Stubbing is a technique used to replace certain method implementations or return values of objects under test. It allows developers to control the behavior of specific methods, making it easier to test different scenarios without relying on the actual implementation or real dependencies. Stubbing is particularly useful when testing complex logic or edge cases.

Here’s an example:

public class MyService {

    public int calculate(int a, int b) {
        // some complex calculation
        return a + b;
    }
}

...

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

public class MyServiceTest {

    @Test
    public void testCalculate() {
        MyService myService = mock(MyService.class);
        when(myService.calculate(2, 3)).thenReturn(5);

        assertEquals(5, myService.calculate(2, 3));
        verify(myService, times(1)).calculate(2, 3);
    }
}

In this example, we have a simple MyService class that performs a calculation. Inside the test method testCalculate(), we create a stub using Mockito’s when() method to replace the calculation with a predefined value. By stubbing the calculate() method, we can test the expected behavior without relying on the actual calculation logic.

Conclusion

Mocking and stubbing are powerful techniques in unit testing that allow developers to control and isolate code under test. By using mocking frameworks like Mockito, we can efficiently simulate interactions with external dependencies and replace certain behaviors. Incorporating these techniques into our unit testing strategy can greatly enhance the quality and effectiveness of our tests.

#Java #UnitTesting