简体   繁体   中英

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?

Consider this as an alternative. I am assuming you are using Java's type Optional and not your own implementation (doing more than I can see here).

The Optional came to Java to avoid a NPE and indicate an abscent of a type at runtime. But in Kotlin you do not really need an Optional, since you can explicitely define your type as nullable T? .

So you can either define it as:

fun getUser(userId: UserId): User?

or

fun getUser(userId: UserId): Optional<User> // not nullable!

You could try willAnswer instead of willReturn :

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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM