realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.74k forks source link

Update example. Kotlin high order function not working with Mock RealmList #7000

Open ppamorim opened 4 years ago

ppamorim commented 4 years ago

This code below does not work when using realm-java in a Kotlin project since high order functions from Kotlin are not automatically handled by this solution that uses the interactor:

https://github.com/realm/realm-java/blob/0ddcc16136d31984aaaec7387a552c1d31a5ccb9/examples/unitTestExample/src/test/java/io/realm/examples/unittesting/ExampleActivityTest.java#L167

A structure as the example below does not work:

@RealmClass
open class User(val messages: RealmList<Message> = RealmList())
val realm = //... get mocked realm, Java code, similar to the code from the example in this repo.

val user = mock(User::class.java)

val userQuery: RealmQuery<User> = mockRealmQuery()

`when`(userQuery.findFirst()).thenReturn(user)
`when`(mockRealm.where(User::class.java)).thenReturn(userQuery)

val message = mock(Message::class.java)
`when`(message.content).thenReturn("Foo")

val messages: RealmList<Message> = mockRealmList()
val messagesList = mutableListOf(message)

`when`(messages.iterator()).thenReturn(messagesList.iterator())
`when`(messages.size).thenReturn(messagesList.size)
`when`(messages[0]).thenReturn(message)
`when`(user.messages).thenReturn(messages)

val user = fetchUser(mockRealm)
user.messages.forEach { message ->
  //Not running
  println("message content: ${message.content}")
}

val contents = user.messages.map { message ->
  //Not running
  return message.content
}

fun fetchUser(realm: Realm): User {
    return mockRealm.where(User::class.java).findFirst()!!
}

I am not sure how this could be sorted, I also opened an issue in the mockito-kotlin repo: https://github.com/nhaarman/mockito-kotlin/issues/385 Also added a question on StackOverflow: https://stackoverflow.com/questions/63042724/how-to-mock-kotlins-list-foreach

ppamorim commented 4 years ago

Sorted with the use of `when`(messages.iterator()).thenAnswer { messagesList.iterator() }. Is this correct?

rorbech commented 2 years ago

@ppamorim Yes, given the explanation in https://stackoverflow.com/a/63064586/6834276 that seems correct.

I guess our example works since it doesn't hit the mocked call multiple times, hence only iterates the list a single time. I guess we should update the example.