← Back to list

How to Unit Test a Coffee Machine: Using Junit & Mockito to Mock Supplier Dependencies

Testing is an essential aspect of software development that ensures code reliability, functionality, and maintainability. In this article…

Ganeshkumar Moorthy · 2025-01-07 06:14 · 4 claps · 3.0 min read
#java #spring-boot #test-case #junit4 #mockito
Open on Medium ↗
Wiki topics: 💻 · Programming 🍳 · Food & Cooking

How to Unit Test a Coffee Machine: Using Junit & Mockito to Mock Supplier Dependencies

Testing is an essential aspect of software development that ensures code reliability, functionality, and maintainability. In this article, we will discuss how to write effective Java test cases using JUnit 4, Mockito, and relevant testing dependencies, focusing on best practices and practical examples.

Imagine you’re building a coffee-making machine that uses a coffee supplier to get coffee beans. Your machine has a method makeCoffee(), but it depends on a supplier's API (getCoffeeBeans()) to provide the beans.

You want to test the makeCoffee() method but don’t want to actually call the supplier API because:

  • The supplier might charge you for each API call.
  • The API might not be available when you’re testing.
  • You want the tests to run fast and repeatedly without relying on external systems.

Here’s where JUnit and Mockito come in.

Example: Testing a Coffee Machine

CoffeeMachine.java

public class CoffeeMachine {
    private CoffeeSupplier supplier;

    public CoffeeMachine(CoffeeSupplier supplier) {
        this.supplier = supplier;
    }

    public String makeCoffee() {
        String beans = supplier.getCoffeeBeans();
        if (beans.equals("Arabica")) {
            return "Coffee made with Arabica beans!";
        } else {
            return "Default coffee made!";
        }
    }
}

CoffeeSupplier.java

public interface CoffeeSupplier {
    String getCoffeeBeans();
}

Writing a Test with JUnit and Mockito

CoffeeMachineTest.java

import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

public class CoffeeMachineTest {

    @Test
    public void testMakeCoffee() {
        // Arrange: Create a mock CoffeeSupplier
        CoffeeSupplier mockSupplier = Mockito.mock(CoffeeSupplier.class);

        // Mock the behavior of the supplier
        when(mockSupplier.getCoffeeBeans()).thenReturn("Arabica");

        // Inject the mock into the CoffeeMachine
        CoffeeMachine coffeeMachine = new CoffeeMachine(mockSupplier);

        // Act: Call the method to be tested
        String result = coffeeMachine.makeCoffee();

        // Assert: Verify the output
        assertEquals("Coffee made with Arabica beans!", result);

        // Verify that the supplier's method was called exactly once
        verify(mockSupplier, times(1)).getCoffeeBeans();
    }
}

Explanation of the Test

Arrange:A mock CoffeeSupplier is created.We configure the mock to return “Arabica” whenever its getCoffeeBeans() method is called.

Act:The makeCoffee() method of CoffeeMachine is called, and it uses the mocked supplier to fetch beans.

Assert:We check if the result of makeCoffee() is as expected.Additionally, we verify that the supplier’s method was called exactly once.

Real-Life Benefits

Fast Testing: No actual API calls or external systems are involved.

Isolated Logic: Focus only on testing the CoffeeMachine logic without worrying about the supplier's implementation.

Error Simulation: You can simulate errors (e.g., API failures) using mocks to test how your system handles them.

Testing Dependencies Overview

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>4.11.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test</artifactId>
        <version>2.7.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-test-autoconfigure</artifactId>
        <version>2.7.5</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Let’s dive deeper into the process of writing test cases

Let’s write a test case for a UserService class that retrieves user details from a repository.

1.getUserDetails Method Test

Production Code:

public class UserService {
    private final UserRepository userRepository;

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

    public User getUserDetails(String userId) {
        return userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found"));
    }
}

Test Code:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetUserDetails_UserExists() {
        // Arrange
        String userId = "123";
        User mockUser = new User("123", "John Doe", "john.doe@example.com");
        when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));

        // Act
        User result = userService.getUserDetails(userId);

        // Assert
        assertNotNull(result);
        assertEquals("John Doe", result.getName());
        assertEquals("john.doe@example.com", result.getEmail());
    }

    @Test(expected = RuntimeException.class)
    public void testGetUserDetails_UserNotFound() {
        // Arrange
        String userId = "456";
        when(userRepository.findById(userId)).thenReturn(Optional.empty());

        // Act
        userService.getUserDetails(userId);

        // Assert: Exception is expected
    }
}

Explanation:

Annotations:

@RunWith(MockitoJUnitRunner.class): Configures Mockito to run the test.

@Mock: Creates mock objects for dependencies.

@InjectMocks: Injects mocked dependencies into the test subject.

Mocking Behavior: The when(...).thenReturn(...) method is used to define the behavior of mocked dependencies.

Assertions: assertNotNull and assertEquals validate the output.

Exception Testing: The expected attribute in @Test checks if the method throws the correct exception.

Best Practices for Writing Test Cases

Use Clear Naming: Test method names should clearly state what is being tested (e.g., testGetUserDetails_UserExists).

Mock External Dependencies: Use Mockito to mock dependencies like repositories or external services.

Focus on One Scenario Per Test: Each test should validate a single behavior or scenario.

Validate All Outcomes: Include both positive (happy path) and negative (edge case) tests.

Isolate Unit Tests: Avoid dependencies on external systems like databases or APIs.


메타데이터
post_id
4c22fa9652d5
slug
how-to-unit-test-a-coffee-machine-using-junit-mockito-to-mock-supplier-dependencies-4c22fa9652d5
url
https://medium.com/@ganeshkumarg024/how-to-unit-test-a-coffee-machine-using-junit-mockito-to-mock-supplier-dependencies-4c22fa9652d5
canonical_url
https://medium.com/@ganeshkumarg024/how-to-unit-test-a-coffee-machine-using-junit-mockito-to-mock-supplier-dependencies-4c22fa9652d5
author_url
https://medium.com/@ganeshkumarg024
status
ok
fetched_at
2026-07-21 10:10:43