top of page
HyperTest_edited.png
21 June 2024
07 Min. Read

Mockito Mocks: A Comprehensive Guide

Mockito Mocks: A Comprehensive Guide

Fast Facts

Get a quick overview of this blog

  1. Isolate unit tests with Mockito mocks to focus on your code's behavior.

  2. Define mock behavior with when() and thenReturn() for granular control.

  3. Mock beyond basics: explore spies and static mocks for complex tests.

  4. Auto generate mocks with HyperTest that lets you create and update mocks for all the other external dependencies.

💡 Mockito is unreadable for a beginner. So I'm just starting with mockito on Java, and god, it's horrible to read. I mean, reading tests in general requires some practice, but when you get there is like documentation on class methods. Is wonderful. Mockito test, on the other hand, are chaotic.

-a mockito user on Reddit

Well, that’s not a good review for such a famous mocking framework. People have their reasons to have varied opinions, but this guide is our attempt to make mockito sorted for you all.


So what is mockito all about?


Unit testing – the cornerstone of building reliable, maintainable software. But unit testing can get tricky when you have complex dependencies. That's where Mockito mocks come in, like a superhero for isolated unit tests.

Mockito is one of the most popular and powerful mocking frameworks used in Java unit testing. It simplifies the creation of test doubles, or "mocks", which mimic the behavior of complex, real objects in a controlled way, allowing developers to focus on the behavior being tested without setting up elaborate real object environments.


Mockito allows testing a method without needing the methods that the method depends on.

Introduction to Mocking


Mocking is a technique used in unit testing where real implementation details are replaced with simulated behaviors. Mock objects return predetermined responses to method calls, ensuring that the test environment is both controlled and predictable. This is crucial in testing the interactions between components without relying on external dependencies.


⏩Mocks


Imagine a mock object as a spy. It pretends to be a real object your code interacts with, but you control its behavior entirely. This lets you test your code's logic in isolation, without worrying about external factors.


Why Mockito?


Mockito’s ease of use and large community-base is great, but there are other reasons also on why it’s a favored choice among Java devs:


  • Flexibility: It allows testing in isolation and provides numerous ways to tailor mock behavior.


  • Readability: Mockito's syntax is considered clear and concise, making your tests easier to understand and maintain.


  • Versatility: It supports mocking both interfaces and classes, offering flexibility in your testing approach.


On the technical front, it offers customizations up to the level of fine-tuning the details in your verifications, keeping tests focused on what matters. Also:


  • Spies: Mockito allows creating spies, which are a type of mock that also record how they were interacted with during the test.


  • Annotations: Mockito provides annotations like @Mock and @InjectMocks for streamlined mock creation and injection, reducing boilerplate code.


  • PowerMock: Mockito integrates with PowerMock, an extension that enables mocking static methods and final classes, giving you more control in complex scenarios.


While other frameworks like EasyMock or JMockit may have their strengths, Mockito's overall ease of use, clear syntax, and extensive features make it a preferred choice for many Java developers.

Code Coverage Challenge

Quick Question

Having trouble getting good code coverage? Let us help you

Getting Started with Mockito


Before right away starting the tech-dive with mockito, let’s first understand some basic jargon terms that comes along with Mockito.


Understanding the Jargon first:

  • Mocking: In Mockito, mocking refers to creating a simulated object that imitates the behavior of a real object you depend on in your code. This allows you to isolate and test your code's functionality without relying on external factors or complex dependencies.


  • Mock Object: A mock object is the fake implementation you create using Mockito. It can be a mock for an interface or a class. You define how the mock object responds when methods are called on it during your tests.


  • Stub: While similar to a mock object, a stub is a simpler version. It often provides pre-programmed responses to specific method calls and doesn't offer the same level of flexibility as a full-fledged mock object.


  • Verification: Mockito allows you to verify interactions with your mock objects. This means checking if a specific method on a mock object was called with certain arguments a particular number of times during your test. Verification helps ensure your code interacts with the mock object as expected.


  • @Mock: This annotation instructs Mockito to create a mock object for the specified class or interface.


  • @InjectMocks: This annotation simplifies dependency injection. It tells Mockito to inject the mock objects created with @Mock into the fields annotated with @InjectMocks in your test class


  • Mockito.when(): This method is used to define the behavior of your mock objects. You specify the method call on the mock object and the value it should return or the action it should perform when that method is invoked.


  • Mockito.verify(): This method is used for verification. You specify the method call you want to verify on a mock object and optionally, the number of times it should have been called.


Now it’s time to see Mockito in practice


Alright, picture a FinTech app. It has two important services:


  • AccountService: This service retrieves information about your account, like the account number.


  • TransactionService: This service handles transactions, like processing a payment.


We'll be using Mockito to mock these services so we can test our main application logic without relying on actual accounts or transactions (safer for our virtual wallet!).


Step 1: Gearing Up (Adding Mockito)

First, we need to include the Mockito library in our project. This is like getting the deck of cards (Mockito) for our testing house of cards. You'll use a tool like Maven or Gradle to manage dependencies, but don't worry about the specifics for now.


Step 2: Mocking the Services (Creating Fake Cards)

Now, let's create mock objects for our AccountService and TransactionService. We'll use special annotations provided by Mockito to do this:

@Mock
private AccountService accountService;

@Mock

private TransactionService transactionService;

// More code will come here...
  • @Mock: This annotation tells Mockito to create fake versions of AccountService and TransactionService for us to play with in our tests.


Mocks
Step 3: Putting it all Together (Building the Test)

We'll create a test class to see how our FinTech app behaves. Here's a breakdown of what goes inside:

@RunWith(MockitoJUnitRunner.class)
public class MyFinTechAppTest {

  @InjectMocks

  private MyFinTechApp finTechApp;

  @Before

  public void setUp() {

    // This line is important!

    MockitoAnnotations.initMocks(this);

  }

  // Our test cases will go here...

}
  • @RunWith(MockitoJUnitRunner.class): This line tells JUnit (the testing framework) to use Mockito's test runner. Think of it as the table where we'll build our house of cards.


  • @InjectMocks: This injects our mock objects (accountService and transactionService) into our finTechApp instance. It's like shuffling the deck (our mocks) and placing them conveniently next to our app (finTechApp) for the test.


  • @Before: This ensures that Mockito properly initializes our mocks before each test case runs. It's like making sure we have a clean deck before each round of playing cards.


Step 4: Test Case 1 - Valid Transaction (Building a Successful House of Cards)

Let's create a test scenario where a transaction is successful. Here's how we'd set it up:
@Test
public void testProcessTransaction_Valid() {

  // What should the mock AccountService return?

  Mockito.when(accountService.getAccountNumber()).thenReturn("1234567890");

  // What should the mock TransactionService do?

  Mockito.when(transactionService.processTransaction(1000.00, "1234567890")).thenReturn(true);

  // Call the method in our app that processes the transaction

  boolean result = finTechApp.processTransaction(1000.0)

Advanced Features


Spy

While mocks return predefined outputs, spies wrap real objects, optionally overriding some methods while keeping the original behavior of others:

List list = new ArrayList();
List spyList = Mockito.spy(list);

// Use spy object as you would with a mock.

when(spyList.size()).thenReturn(100);

Capturing Arguments

For verifying parameters passed to mock methods, Mockito provides ArgumentCaptor:

ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
verify(mockedList).get(captor.capture());

assertEquals(Integer.valueOf(0), captor.getValue());

A better approach to Mockito Mocks


Mocks generated by mockito are useful, considering the isolation it provides. But the same work can be eased out and performed better by HyperTest.


HyperTest mocks external components and auto-refreshes mocks when dependencies change behavior. It smartly mocks external systems like databases, queues, downstream or 3rd party APIs that your code interacts with.


It also smartly auto-refreshes these mocks as dependencies change their behavior keeping tests non-flaky, deterministic, trustworthy and consistent.


Know more about this approach here in our exclusive whitepaper.

Test generation mode and Test Mode

Conclusion


Mockito mocks offer a robust framework for effectively isolating unit tests from external dependencies and ensuring that components interact correctly. By understanding and utilizing the various features of Mockito, developers can write cleaner, more maintainable, and reliable tests, enhancing the overall quality of software projects.


To know more about the automated mock generation process of HyperTest, read it here.

Related to Integration Testing

Frequently Asked Questions

1. What is the difference between a mock and a spy in Mockito?

Mocks are completely fake objects, while spies are real objects wrapped by Mockito. Mocks let you define all behavior, spies keep real behavior but allow customizing specific methods.

2. Can Mockito mock static methods?

Yes, Mockito can mock static methods since version 3.4. You use Mockito.mockStatic() to create a scoped mock for the static class.

3. How do you create a mock object in Mockito?

Use Mockito.mock(ClassToMock.class) to create a mock object. This replaces a real object with a fake one you control in your test.

For your next read

Dive deeper with these related posts!

What is Mockito Mocks: Best Practices and Examples
05 Min. Read

What is Mockito Mocks: Best Practices and Examples

What is Unit testing? A Complete Step By Step Guide
10 Min. Read

What is Unit testing? A Complete Step By Step Guide

Most Popular Unit Testing Tools in 2024
09 Min. Read

Most Popular Unit Testing Tools in 2024

bottom of page