Say we have a service:
@Servicepublic class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) { this.productRepository = productRepository; }
public List<String> getProductNamesWithEvenNoOfChar() { List<String> names = productRepository.getProductNames(); List<String> result = new ArrayList<>(); for (String n : names) { if (n.length() % 2 != 0) { result.add(n); } } return result; }}And a repository:
@Repositorypublic class ProductRepository {
public List<String> getProductNames() { return Arrays.asList("aaa", "bb", "cacc", "aca"); }}We can test it by calling the method under test and using assert to check the result:
@SpringBootTestclass TestingApplicationTests {
@Autowired private ProductService productService;
@Test void noProductsReturnedTest() { List<String> res = productService.getProductNamesWithEvenNoOfChar();
assertTrue(res.isEmpty()); // assert is used for checking results of tests }}This test fails, because getProductNamesWithEvenNoOfChar() actually returns products with an
odd number of characters — but it does so by calling the repository, whose real implementation
returns a fixed list. Testing the service ends up depending on the repository’s real behavior.
This is the typical case for mocking the repository, using Mockito’s @MockBean.
Mocking creates a fake object standing in for a dependency, which you can control. Here, a fake
ProductRepository that returns whatever list we want:
@MockBean private ProductRepository productRepository;
@Autowired private ProductService productService;
@Test void noProductsReturnedTest() { given(productRepository.getProductNames()) .willReturn(Collections.emptyList());
List<String> res = productService.getProductNamesWithEvenNoOfChar();
assertTrue(res.isEmpty()); }We tell the mock what to return when called (given(...).willReturn(...)), call the method under
test, then assert on the result — a test is assumptions, a method call, then expectations.
We can also test that the method returns something real:
@Test public void moreProductsAreFoundTest() { List<String> input = Arrays.asList("aa", "bbbb", "ccc"); // input list
given(productRepository.getProductNames()).willReturn(input);
List<String> res = productService.getProductNamesWithEvenNoOfChar();
assertEquals(2, res.size()); }When unit testing a class (like a service) that depends on other classes (like repositories), you typically mock the dependencies and inject them into the class under test — isolating it and controlling its dependencies’ behavior. Here’s the same idea with plain Mockito instead of a full Spring context:
import org.junit.jupiter.api.Test;import org.mockito.InjectMocks;import org.mockito.Mock;import static org.mockito.Mockito.*;import org.mockito.junit.jupiter.MockitoExtension;import org.junit.jupiter.api.extension.ExtendWith;
import java.util.Arrays;import java.util.List;
@ExtendWith(MockitoExtension.class)public class ProductServiceUnitTest {
@Mock private ProductRepository productRepository;
@InjectMocks private ProductService productService;
@Test public void getProductNamesWithEvenNoOfCharTest() { when(productRepository.getProductNames()).thenReturn(Arrays.asList("aa", "bbb", "cccc", "ddddd"));
List<String> res = productService.getProductNamesWithEvenNoOfChar();
assertEquals(2, res.size()); assertTrue(res.containsAll(Arrays.asList("aa", "cccc"))); }}When testing a controller, the same pattern applies: @Mock the services and other injected
classes, and @InjectMocks on the controller class itself.