MockitoSession vs MockitoJUnitRunner
Fast recall
Quick revision
Core answer
MockitoSession gives explicit programmatic lifecycle control: build it with Mockito.mockitoSession(), call startMocking(), and always call finishMocking() so strictness validation and cleanup run. MockitoJUnitRunner integrates Mockito with JUnit 4 and owns that lifecycle for a test class. In JUnit Jupiter, @ExtendWith(MockitoExtension.class) is the normal choice. A session is useful for a custom framework or lifecycle, not because its methods are openSession and closeSession—those methods do not exist.Interview-ready guide
Interview answer
MockitoSession provides explicit programmatic control over Mockito's lifecycle. I create it with Mockito.mockitoSession(), optionally initialize annotated fields and choose strictness, then call startMocking(). In teardown I call finishMocking() so unused-stub validation and cleanup are not skipped. A try/finally structure is useful in a custom harness.
MockitoJUnitRunner is the JUnit 4 integration. It initializes Mockito annotations and manages the lifecycle for the test class. JUnit Jupiter does not use JUnit 4 runners, so @ExtendWith(MockitoExtension.class) is the normal JUnit 5 form.
MockitoAnnotations.openMocks(this) is easy to confuse with a session. It returns an AutoCloseable that must be closed, but it is a different API. There are no openSession or closeSession methods on MockitoSession.
MockitoSession vs MockitoJUnitRunner
Direct Answer
MockitoSession gives explicit programmatic lifecycle control: build it with Mockito.mockitoSession(), call startMocking(), and always call finishMocking() so strictness validation and cleanup run. MockitoJUnitRunner integrates Mockito with JUnit 4 and owns that lifecycle for a test class. In JUnit Jupiter, @ExtendWith(MockitoExtension.class) is the normal choice. A session is useful for a custom framework or lifecycle, not because its methods are openSession and closeSession—those methods do not exist.
Code Example
// Manual MockitoSession (framework-agnostic)
class ManualMockitoTest {
private MockitoSession mockitoSession;
private PaymentGateway gateway;
void setup() {
mockitoSession = Mockito.mockitoSession()
.initMocks(this) // initializes @Mock fields
.strictness(Strictness.STRICT_STUBS)
.startMocking();
gateway = mock(PaymentGateway.class); // or use @Mock field
}
void teardown() {
mockitoSession.finishMocking(); // validates stubs, cleans up
}
}
// JUnit 4 with MockitoJUnitRunner (deprecated for new projects)
@RunWith(MockitoJUnitRunner.class) // JUnit 4 only
class JUnit4MockitoTest {
@Mock
private PaymentGateway gateway; // runner initializes this
}
// JUnit 5 with MockitoExtension (modern approach)
@ExtendWith(MockitoExtension.class) // JUnit 5
class JUnit5MockitoTest {
@Mock
private PaymentGateway gateway; // extension initializes this
}
Common Mistakes & Pitfalls
- Using MockitoJUnitRunner in JUnit 5: Trying to use @RunWith(MockitoJUnitRunner.class) in a JUnit 5 test class—JUnit 5 doesn't support runners, causing a runtime error that MockitoJUnitRunner is not found or ignored.
- Forgetting to close MockitoSession: Opening a session with startMocking() but never calling finishMocking(), which leaks resources and prevents strict stubbing validation from running.
- Mixing initialization styles: Using @ExtendWith(MockitoExtension.class) and also manually creating a MockitoSession in @BeforeEach—you initialize mocks twice, which can cause subtle issues and is completely redundant.
Check your understanding
Answer these without looking back at the article.
- How do you enable strict stubbing in Mockito 5?
- What is the difference between STRICT_STUBS and LENIENT strictness levels?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.