There is a documentation on how to use @MockitoSpyBean, but the problem is how to use it properly with Kotlin. There are only examples with Java.

Before Spring Boot 3.4, I was able to create and use mock with @SpyBean like this:

@Configuration
@SpyBeans(
    SpyBean(SomeProvider::class),
    SpyBean(SecondProvider::class)
)
class TestConfiguration
class TestSteps(
    private val someProvider: SomeProvider,
) {
    @Before
    fun before() {
        doReturn("value").whenever(someProvider).getSomeValue(any())
    }

Now that these annotations are deprecated, I want to migrate them to @MockitoSpyBean.

Should that look like the following?

@Configuration
@MockitoSpyBeans(
   MockitoSpyBean(types = [SomeProvider::class]),
   MockitoSpyBean(types = [SecondProvider::class])
)
class TestConfiguration
class TestSteps(
    private val someProvider: SomeProvider,
) {
    @Before
    fun before() {
        doReturn("value").whenever(someProvider).getSomeValue(any())
    }

With above code the mocks aren't working anymore because of this error:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();

Tried this and other solutions like creating mocks in fields inside TestSteps, but nothing worked.

Could you provide documentation on how to migrate the code?

Comment From: sbrannen

@MockitoSpyBean is not supported on a @Configuration class (see #33934).


What happens if you try the following?

@Configuration
class TestConfiguration {
    // ...
}
@SpringJUnitConfig(TestConfiguration::class)
@TestConstructor(autowireMode = AutowireMode.ALL)
@MockitoSpyBean(types = [SomeProvider::class, SecondProvider::class])
class TestSteps(
    private val someProvider: SomeProvider
) {

    @BeforeEach
    fun before() {
        doReturn("value").whenever(someProvider).getSomeValue(any())
    }

Also, have you read the Kotlin Testing sections of the reference documentation?

Comment From: g4iner

Unfortunately I'm using Cucumber for my tests instead of JUnit, so this documentation section doesn't provide adequate information.

I added this part and removed TestConfiguration (because this class was only used to create SpyBeans):

@TestConstructor(autowireMode = AutowireMode.ALL)
@MockitoSpyBean(types = [SomeProvider::class, SecondProvider::class])
class TestSteps(
    private val someProvider: SomeProvider
) {

but the problem still exists, maybe because of the use of Cucumber? I have some standard configuration for that in addition to above TestSteps:

@RunWith(Cucumber::class)
class CucumberTest

@CucumberContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SpringIntegrationTest

Is it possible to configure this properly with Cucumber instead of JUnit?