mockito / mockito-kotlin

Using Mockito with Kotlin
MIT License
3.11k stars 201 forks source link

Mocking an interface with non-nullable properties sets the properties as null #372

Open jordigarcl opened 4 years ago

jordigarcl commented 4 years ago

It looks like Mockito is using null as a default value for properties in a interface even though they are non-nullable.

Reproduce:

interface Dog {
  val name: String
}

class DogCaller {
  fun callDog(dog: Dog) = callSomeone(dog.name)
  private fun callSomeone(name: String) = "Hey $name come here!"
}

class DogCallerTests {

  private val dogCaller = DogCaller()

  @Test
  fun `dog caller should call dog by its name`() {
    val beagle: Dog = mock()

    // This makes the test pass 
    // whenever(beagle.name).thenReturn("Firulais")

    dogCaller.callDog(beagle)

    verify(beagle).name // This fails cause it detects dog.name : String = null !
  }
}
bohsen commented 4 years ago

Your reproducer passes when I try it out. Maybe try checking your imports.

Also returning null is the expected behaviour when a method hasn't been stubbed (depending on the type) - more info here.

jordigarcl commented 4 years ago

Sorry, now I see I got this error cause inside callDog() I passed dog.name to another function which expected a non-nullable type. That's where the nullability of String check failed.

Though from thecastNull() in the file you referenced I see this is a totally intentional behaviour. Should it be the case though? String has always been a "special" type. I expected the mock to return a '"nice" value such as "".

bohsen commented 4 years ago

It would make sense to handle it that way. Would actually solve the issue seen in #241 without using the proposed workaround I believe. Strings have always been kind of problematic in regards to Mockito-kotlin.