HomeTesting › Mockito Hub

🌟 Definitive Guide

The Complete Mockito Guide

Everything you need to know about Mockito in one place — @Mock, @InjectMocks, stubbing, verification, ArgumentCaptor, Spy, Spring Boot MockBean, and interview Q&A.

Advertisement

1. Setup & Dependencies

Add Mockito to your project — Maven & Gradle

Mockito ships inside spring-boot-starter-test (no extra dependency needed for Spring Boot projects). For plain Java, add:

<!-- Maven (pom.xml) --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>5.11.0</version> <scope>test</scope> </dependency> <!-- JUnit 5 integration (mockito-junit-jupiter) --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>5.11.0</version> <scope>test</scope> </dependency>
// Gradle (build.gradle) testImplementation 'org.mockito:mockito-core:5.11.0' testImplementation 'org.mockito:mockito-junit-jupiter:5.11.0'
💡 Spring Boot tip: If you use spring-boot-starter-test, Mockito is already on the classpath. Just annotate your test with @ExtendWith(MockitoExtension.class) and you're ready.

2. Core Annotations

@Mock, @InjectMocks, @Spy, @Captor — when to use each

@Mock

Creates a fully fake object. Every method returns a zero/null/empty default unless you stub it. The class is never instantiated — no real code runs.

@InjectMocks

Creates the real class under test and injects all @Mock fields into it via constructor injection, then setter injection, then field injection.

@Spy

Wraps a real object. Unstubbed method calls execute the real implementation; stubbed calls return your defined value. Useful for partial mocking.

@Captor

Declares an ArgumentCaptor inline. Use it with verify() to capture and inspect the argument passed to a mock method call.

@ExtendWith(MockitoExtension.class) class OrderServiceTest { @Mock private PaymentGateway paymentGateway; // fake — no real HTTP calls @Mock private OrderRepository orderRepository; // fake — no real DB @InjectMocks private OrderService orderService; // real class being tested @Captor private ArgumentCaptor<Order> orderCaptor; @Test void placeOrder_savesOrderToRepository() { Order order = new Order("item-1", "USD", 100); orderService.placeOrder(order); verify(orderRepository).save(orderCaptor.capture()); assertThat(orderCaptor.getValue().getCurrency()).isEqualTo("USD"); } }

3. Stubbing — when / thenReturn / thenThrow

Control what a mock returns when a method is called

// Basic stubbing when(orderRepository.findById("id-1")) .thenReturn(Optional.of(new Order("id-1"))); // Throw an exception when(paymentGateway.charge(any())) .thenThrow(new PaymentException("Card declined")); // Return different values on consecutive calls when(orderRepository.count()) .thenReturn(0L) .thenReturn(1L) .thenReturn(2L); // Custom logic with thenAnswer when(orderRepository.save(any(Order.class))) .thenAnswer(inv -> { Order o = inv.getArgument(0); o.setId(UUID.randomUUID().toString()); return o; }); // Argument matchers when(orderRepository.findByStatus(eq("PENDING"))) .thenReturn(List.of(order1, order2)); when(orderRepository.findByAmount(anyDouble())) .thenReturn(List.of());
💡 Rule: Either use no matchers (exact values) OR use matchers for all arguments in a single stub call. Mixing throws a InvalidUseOfMatchersException.

4. Stubbing Void Methods

when().thenReturn() does not work for void — use doXxx() instead

// Do nothing (default for void mocks, but explicit is clearer) doNothing().when(emailService).send(any()); // Throw from a void method doThrow(new RuntimeException("SMTP error")) .when(emailService).send(argThat(e -> e.getTo().contains("bad@"))); // Custom behavior from a void method doAnswer(inv -> { String recipient = inv.getArgument(0); System.out.println("Sending to: " + recipient); return null; // void methods must return null }).when(emailService).send(any());
SyntaxUse caseWorks on void?
when(m.foo()).thenReturn(x)Stub return value❌ No
when(m.foo()).thenThrow(ex)Stub exception (non-void)❌ No
doReturn(x).when(m).foo()Stub return (avoids real call on Spy)❌ No
doNothing().when(m).foo()Suppress void method✅ Yes
doThrow(ex).when(m).foo()Throw from void method✅ Yes
doAnswer(inv -> …).when(m).foo()Custom logic✅ Yes

5. Verification

Assert how many times — and with what arguments — a method was called

// Called exactly once (default) verify(orderRepository).save(any(Order.class)); // Called exactly N times verify(emailService, times(2)).send(any()); // Never called verify(paymentGateway, never()).charge(any()); // At least / at most verify(orderRepository, atLeastOnce()).findById(any()); verify(orderRepository, atMost(3)).findAll(); // No more interactions on the mock verifyNoMoreInteractions(orderRepository); // No interactions at all verifyNoInteractions(paymentGateway); // Order matters — use InOrder InOrder inOrder = inOrder(orderRepository, emailService); inOrder.verify(orderRepository).save(any()); inOrder.verify(emailService).send(any());

6. ArgumentCaptor

Capture the exact argument passed to a mock to assert its content

Use ArgumentCaptor when you need to inspect the full object passed to a mock — not just verify it was called.

@Test void placeOrder_sendsConfirmationEmail() { // Arrange ArgumentCaptor<EmailRequest> emailCaptor = ArgumentCaptor.forClass(EmailRequest.class); // Act orderService.placeOrder(new Order("item-1", "[email protected]")); // Capture and assert verify(emailService).send(emailCaptor.capture()); EmailRequest sentEmail = emailCaptor.getValue(); assertThat(sentEmail.getTo()).isEqualTo("[email protected]"); assertThat(sentEmail.getSubject()).contains("Order Confirmed"); } // Capture multiple invocations verify(emailService, times(3)).send(emailCaptor.capture()); List<EmailRequest> allEmails = emailCaptor.getAllValues();
💡 When to use Captor vs matchers: Prefer eq() / any() matchers for simple assertions. Use ArgumentCaptor when you need to assert multiple fields of the captured object, or when the object is built internally by the class under test.

7. @Spy — Partial Mocking

Wrap a real object and stub only what you need

Feature@Mock@Spy
Object typeFully fake (proxy)Real object (wrapped)
Unstubbed methodReturns null/0/falseCalls real method
Use caseIsolate dependenciesPartial mock of a real class
RiskStubs may drift from real behaviourReal calls can have side-effects
@Spy private AuditLogger auditLogger = new AuditLogger(); // real instance @Test void spy_onlyStubsSpecificMethod() { // Only stub the file-write — everything else runs real code doNothing().when(auditLogger).writeToFile(any()); auditLogger.log("Payment processed"); // real method runs verify(auditLogger).writeToFile(contains("Payment")); }
⚠️ Spy gotcha: Never use when(spy.method()).thenReturn(x) on a Spy — the real method is called during the stubbing. Always use doReturn(x).when(spy).method() instead.

8. Spring Boot Integration — @MockBean & MockMvc

Replace Spring beans with Mockito mocks in slice and full context tests

AnnotationContextWhen to use
@MockNo Spring contextPure unit tests — fast
@MockBeanSpring context (loaded)Controller slice tests (@WebMvcTest), integration tests (@SpringBootTest)
@SpyBeanSpring context (loaded)Spy on a real Spring bean
// @WebMvcTest — test controller layer only, mock the service @WebMvcTest(OrderController.class) class OrderControllerTest { @Autowired private MockMvc mockMvc; @MockBean private OrderService orderService; // added to Spring context as a Mockito mock @Test void getOrder_returns200() throws Exception { when(orderService.findById("id-1")) .thenReturn(new Order("id-1", "PENDING")); mockMvc.perform(get("/api/orders/id-1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("PENDING")); } }
💡 @MockBean resets after each test — you don't need to call reset() manually. Use @SpyBean when you need both the real Spring bean behaviour and the ability to verify interactions on it.

Related Spring Boot Testing Articles

9. Common Mistakes & Anti-Patterns

❌ Mocking the class under test

Never put @Mock on the class you are actually testing. That class should be annotated with @InjectMocks (or constructed manually) and receive real execution.

❌ Over-verifying

Avoid verifying every single interaction. Verify only the interactions that are meaningful to the test's intent. verifyNoMoreInteractions() on every test makes refactoring painful.

❌ Mocking value objects

Don't mock simple data holders (Order, User). Create real instances. Mocking them adds noise and hides the actual structure being tested.

❌ Stubbing on Spy with when()

On a @Spy, when(spy.method()).thenReturn(x) calls the real method during stubbing. Always use doReturn(x).when(spy).method() to avoid side-effects.

❌ Mixing matchers and literals

when(m.foo("exact", any())) will throw InvalidUseOfMatchersException. Either use exact values for all args, or wrap all args with matchers like eq("exact").

❌ Static methods (classic Mockito)

Mockito 5 supports mocking statics with mockStatic() (try-with-resources). But prefer refactoring static calls behind an interface instead — it makes code more testable long-term.

10. Mockito Interview Questions & Answers

The questions you'll actually be asked — with crisp, complete answers

Q1. What is Mockito and why is it used?

Mockito is a Java mocking framework that creates fake (mock) objects for unit testing. It lets you isolate the class under test from its dependencies (database, HTTP client, etc.), define what each mock should return when called, and verify that specific methods were called. It integrates with JUnit 5 via @ExtendWith(MockitoExtension.class).

Q2. What is the difference between @Mock and @InjectMocks?

@Mock creates a mock (fake) instance of a class or interface — no real code runs. @InjectMocks creates the real instance of the class under test and automatically injects all @Mock and @Spy fields into it (constructor → setter → field injection).

Q3. @Mock vs @Spy — when do you use each?

Use @Mock when you want a completely fake object — no real logic runs at all. Use @Spy when you want the real object's behaviour for most methods, but need to stub or verify one or two specific methods without executing their real code.

Q4. How do you stub a void method in Mockito?

You cannot use when(...).thenReturn() for void methods. Instead use: doNothing().when(mock).voidMethod(), doThrow(ex).when(mock).voidMethod(), or doAnswer(inv -> null).when(mock).voidMethod().

Q5. What is ArgumentCaptor and when should you use it?

ArgumentCaptor captures the actual argument passed to a mocked method so you can assert its value. Use it when the argument is constructed inside the class under test and you cannot pass it in directly. Declare with @Captor or ArgumentCaptor.forClass(), call verify(mock).method(captor.capture()), then inspect with captor.getValue().

Q6. What is the difference between @Mock and @MockBean?

@Mock (plain Mockito) creates a mock with no Spring context — very fast. @MockBean (spring-boot-test) creates a Mockito mock AND registers it as a bean inside the loaded Spring ApplicationContext, replacing any existing bean of that type. Use @MockBean in @WebMvcTest or @SpringBootTest; use @Mock in pure unit tests.

Q7. Can you mock static methods in Mockito 5?

Yes. Use MockedStatic<T> mocked = mockStatic(MyClass.class) inside a try-with-resources block. Inside the block, mocked.when(() -> MyClass.staticMethod()).thenReturn(value) stubs the static call. Best practice is to avoid static coupling by injecting the static behaviour through an interface, which makes the design more testable without needing mockStatic.

Q8. What does verifyNoMoreInteractions() do and when should you avoid it?

It asserts that no other methods were called on the mock beyond those already verified. Avoid adding it to every test — it couples your tests tightly to implementation details, making refactoring expensive even when behaviour hasn't changed. Use it only when unexpected interactions represent a real bug risk.

Q9. What happens if @InjectMocks cannot inject — does it fail silently?

Yes — Mockito silently skips injection if no matching constructor, setter, or field is found, rather than throwing an exception. This is a known pitfall. Always write a smoke-test assertion (e.g., assertNotNull(service)) or use constructor injection to make the dependency explicit and avoid silent failures.

Q10. How do you test a method that calls another method on the same class?

If method A calls method B on the same object, a plain @Mock cannot help (it mocks the entire class). Use a @Spy on the real class, then stub only method B: doReturn(value).when(spy).methodB(). Alternatively, extract the inner logic into a collaborator and inject it — which is cleaner and avoids partial mocking.

More Testing Interview Questions →

All Mockito Articles on This Site

Every Mockito tutorial — with topic and difficulty level

ArticleTopic FocusLevelDate
Mockito Tutorial for Beginners (2026) — Step-by-Step Guide @Mock, when/thenReturn, verify Beginner 2026-04-10
Mockito Tutorial with Real-Time Examples (Beginner to Advanced) Full lifecycle — mock → stub → verify Intermediate 2026-04-10
Mockito Tutorial — Unit Testing Made Easy Setup, annotations, common patterns Beginner 2026-04-09
Mockito Tutorial for Beginners Step by Step with Examples @InjectMocks, thenReturn, thenThrow Beginner 2026-04-09
Mockito with JUnit — Complete Testing Guide with Examples JUnit 5 + Mockito integration Intermediate 2026-04-09
Spring Boot Unit Testing with JUnit 5 and Mockito @MockBean, @WebMvcTest, MockMvc Intermediate 2026-04-06
Spring Boot Testing Interview Questions — JUnit & Mockito 2026 Interview prep — @MockBean, verify, ArgumentCaptor Advanced 2026-03-25
Mastering Spring Boot Unit Testing with JUnit 5 and Mockito Deep dive — Spy, Captor, SliceTests Advanced 2026-03-24
Getting Started With Mockito and JUnit First Mockito test — absolute basics Beginner 2023-01-08

Master Mockito Once — Write Better Tests Forever

Bookmark this page as your go-to Mockito reference. 9 deep-dive articles, all linked above.

Search All Mockito Posts →