mockito / mockito-kotlin

Using Mockito with Kotlin
MIT License
3.09k stars 198 forks source link

Why mockito cannot mock fun interface? #442

Closed Jacks0N23 closed 2 years ago

Jacks0N23 commented 2 years ago

For ex. my code looks like this:

fun interface FunInterfaceToTest : (String) -> Int

val myInterfaceToTest: FunInterfaceToTest = spy(
    FunInterfaceToTest { mock() }
)

If new IR kotlin compiler backend is enabled then

launching test with SAM throws this:

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class my.company.package.test$sam$my_company_package_FunInterfaceToTest$0.
Can not mock final classes with the following settings :
 - explicit serialization (e.g. withSettings().serializable())
 - extra interfaces (e.g. withSettings().extraInterfaces(...))

You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.

OR if use anonymous object than i got this:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.lang.Integer
Mockito cannot mock/spy because :
 - Cannot mock wrapper types, String.class or Class.class

in some cases I got this:

Argument passed to verify() is of type  and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
    verify(mock).someMethod();
    verify(mock, times(10)).someMethod();
    verify(mock, atLeastOnce()).someMethod();
org.mockito.exceptions.misusing.NotAMockException: 

BUT If in build.gradle file I enable old kotlin compiler backend than

android {
    kotlinOptions {
        useOldBackend = true
    }
}

everything works fine, but why??

Full Test Suite ```kotlin class Test : BehaviorSpec({ Given("test given") { val myInterfaceToTest: FunInterfaceToTest = spy( object : FunInterfaceToTest { override fun invoke(it: String): Int { return mock() } } ) When("test when") { myInterfaceToTest("") Then("so") { verify(myInterfaceToTest, never()).invoke(any()) } } } }) fun interface FunInterfaceToTest : (String) -> Int ```
abelkov commented 2 years ago

See explanation in https://github.com/mockito/mockito-kotlin/issues/441