Support strict stubbing for @MockitoBean
and @MockitoSpyBean
#34419
Labels
in: test
Issues in the test module
status: blocked
An issue that's blocked on an external project change
type: enhancement
A general enhancement
Milestone
Overview
As explained in #33692, due to limitations in Mockito it is not currently possible to support strict stubbing for mocks and spies created via
@MockitoBean
and@MockitoSpyBean
.This issue therefore serves as a placeholder to collaborate with the Mockito team to investigate a way to provide such support.
Known Issues
MockitoSession
simultaneously. Only oneMockitoSession
can exist at any given time for the current thread.MockitoTestExecutionListener
that existed during the 6.2 milestone phase attempted to emulate the behavior of Mockito's ownMockitoExtension
; however, a SpringTestExecutionListener
cannot achieve the same level of integration into JUnit Jupiter's extension model.TestExecutionListener
cannot access the enclosing test instances for@Nested
test classes.TestExecutionListener
cannot store state in a parentTestContext
(simply because there is no parent).MockitoTestExecutionListener
provided less benefit than using theMockitoExtension
when it comes to JUnit Jupiter support.Results of exploratory research
MockitoSession
is effectively a "Unit of Work" that is bound to the current thread via aThreadLocal
. Mocks created between the "start" and "finish" of the session are tracked for the current thread only. Mocks created outside that session -- for example, before the session or in another thread -- are not tracked by the session. In addition, there is no API that allows one to attach an existing mock to aMockitoSession
, and there is no API to query whether aMockitoSession
already exists for the current thread.The following provides an overview of how
MockitoSession
technically works.startMocking()
invokes:MockitoAnnotations.openMocks()
startMocking()
registers:org.mockito.internal.junit.UniversalTestListener
finishMocking()
unregisters:org.mockito.internal.junit.UniversalTestListener
finishMocking()
invokes:Mockito.validateMockitoUsage()
Hypothetically (and this is not tested in any way, shape, or form), if we wanted to mimic
MockitoSession
support for mocks created via@MockitoBean
and@MockitoSpyBean
, we could track theMockCreationSettings
inMockitoBeanOverrideMetadata.createMock()
and then register a (subclass of)UniversalTestListener
viaMockito.framework().addListener()
and invokeCustomSubclassOfUniversalTestListener.onMockCreated(Object, MockCreationSettings)
with the mock created byMockitoBeanOverrideMetadata
and the savedMockCreationSettings
inMockitoTestExecutionListener.beforeTestMethod()
, and we could then invokeMockito.framework().removeListener()
andMockito.validateMockitoUsage()
inMockitoTestExecutionListener.afterTestMethod()
.However,
UniversalTestListener
is an internal implementation detail of Mockito and resides in theorg.mockito.internal.junit
package, and we should ideally not rely on Mockito internals that may change unexpectedly.Instead, we should approach the Mockito team to discuss alternatives to the current
MockitoSession
API and semantics that would allow us to provide similar support to mocks that we choose and within a scope that we define.Related Issues
MockitoTestExecutionListener
to enable strict stubbing #33318MockitoTestExecutionListener
no longer opens mocks in theprepareTestInstance()
callback #33690@MockitoBeanSettings
and support forMockitoSession
management #33692The text was updated successfully, but these errors were encountered: