javakotlinoption-typemockito-kotlin

Can't mock `willReturn` with Optional in Kotlin


I have a method

fun getUser(userId: UserId): Optional<User?> = userRepository.findById(userId)

that returns an Optional in Java. So I want to mock that method call in my Kotlin unit test.

This was my first guess...

given { mockedUserService.getUser(currentUser.userId) }.willReturn(Optional.of(currentUser))

... but the compiler says no

Type mismatch: inferred type is Optional but Optional<User?>! was expected

So I started to make the val currentUser: User? just to make the compiler happy.

given { currentUser?.userId?.let { mockedUserService.getUser(it) }.willReturn(Optional.of(currentUser))

Type mismatch: inferred type is Optional but Optional<User?>? was expected

Type mismatch: inferred type is User? but TypeVariable(T) was expected

And now I am somewhat lost. How can I make the compiler happy?


Solution

  • One way would be to fix the test, but that is actually not the problem here. You should avoid Optional whenever possible in Kotlin. Java's type system has no way to distinguish nullable and non-nullable values. Kotlin does, so you should transform the Optional<T> as early as possible to T?.

    You can easily fix your function like that:

    fun getUser(userId: UserId): User? = userRepository.findById(userId).orElse(null)