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…
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