Migrate all remaining mockito tests to mockk.

Resolves #13835
This commit is contained in:
Jameson Williams
2024-12-10 21:19:10 -06:00
committed by Greyson Parrelli
parent 57eeed33f0
commit 34a003c68c
11 changed files with 272 additions and 263 deletions

View File

@@ -2,20 +2,19 @@ package org.thoughtcrime.securesms.contacts.paged
import android.app.Application
import androidx.core.os.bundleOf
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import org.junit.Assert
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.isNull
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.thoughtcrime.securesms.MockCursor
import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.recipients.LiveRecipientCache
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
@@ -23,26 +22,28 @@ import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class ContactSearchPagedDataSourceTest {
private val repository: ContactSearchPagedDataSourceRepository = mock()
private val cursor: MockCursor = mock()
private val repository = mockk<ContactSearchPagedDataSourceRepository>(relaxed = true)
private val cursor = mockk<MockCursor>(relaxed = true)
private val groupStoryData = ContactSearchData.Story(Recipient.UNKNOWN, 0, DistributionListPrivacyMode.ALL)
@Before
fun setUp() {
whenever(repository.getRecipientFromGroupRecord(any())).thenReturn(Recipient.UNKNOWN)
whenever(repository.getRecipientFromSearchCursor(any())).thenReturn(Recipient.UNKNOWN)
whenever(repository.getRecipientFromThreadCursor(cursor)).thenReturn(Recipient.UNKNOWN)
whenever(repository.getRecipientFromDistributionListCursor(cursor)).thenReturn(Recipient.UNKNOWN)
whenever(repository.getPrivacyModeFromDistributionListCursor(cursor)).thenReturn(DistributionListPrivacyMode.ALL)
whenever(repository.getGroupStories()).thenReturn(emptySet())
whenever(repository.getLatestStorySends(any())).thenReturn(emptyList())
whenever(cursor.getString(any())).thenReturn("A")
whenever(cursor.moveToPosition(any())).thenCallRealMethod()
whenever(cursor.moveToNext()).thenCallRealMethod()
whenever(cursor.position).thenCallRealMethod()
whenever(cursor.isLast).thenCallRealMethod()
whenever(cursor.isAfterLast).thenCallRealMethod()
mockkStatic(AppDependencies::class)
every { AppDependencies.recipientCache } returns mockk<LiveRecipientCache>(relaxed = true)
every { repository.getRecipientFromGroupRecord(any()) } returns Recipient.UNKNOWN
every { repository.getRecipientFromSearchCursor(any()) } returns Recipient.UNKNOWN
every { repository.getRecipientFromThreadCursor(cursor) } returns Recipient.UNKNOWN
every { repository.getRecipientFromDistributionListCursor(cursor) } returns Recipient.UNKNOWN
every { repository.getPrivacyModeFromDistributionListCursor(cursor) } returns DistributionListPrivacyMode.ALL
every { repository.getGroupStories() } returns emptySet()
every { repository.getLatestStorySends(any()) } returns emptyList()
every { cursor.getString(any()) } returns "A"
every { cursor.moveToPosition(any()) } answers { callOriginal() }
every { cursor.moveToNext() } answers { callOriginal() }
every { cursor.position } answers { callOriginal() }
every { cursor.isLast } answers { callOriginal() }
every { cursor.isAfterLast } answers { callOriginal() }
}
@Test
@@ -99,7 +100,6 @@ class ContactSearchPagedDataSourceTest {
Assert.assertEquals(expected, resultKeys)
}
@Ignore
@Test
fun `Given storiesWithHeaderAndExtras, when I load 11, then I expect properly structured output`() {
val testSubject = createStoriesSubject()
@@ -176,9 +176,9 @@ class ContactSearchPagedDataSourceTest {
)
}
whenever(repository.getStories(anyOrNull())).thenReturn(cursor)
whenever(repository.recipientNameContainsQuery(Recipient.UNKNOWN, null)).thenReturn(true)
whenever(cursor.count).thenReturn(10)
every { repository.getStories(any()) } returns cursor
every { repository.recipientNameContainsQuery(Recipient.UNKNOWN, null) } returns true
every { cursor.count } returns 10
return ContactSearchPagedDataSource(configuration, repository)
}
@@ -201,10 +201,10 @@ class ContactSearchPagedDataSourceTest {
)
}
whenever(repository.getRecents(recents)).thenReturn(cursor)
whenever(repository.queryNonGroupContacts(isNull(), any())).thenReturn(cursor)
whenever(repository.querySignalContacts(any())).thenReturn(cursor)
whenever(cursor.count).thenReturn(10)
every { repository.getRecents(recents) } returns cursor
every { repository.queryNonGroupContacts(isNull(), any()) } returns cursor
every { repository.querySignalContacts(any()) } returns cursor
every { cursor.count } returns 10
return ContactSearchPagedDataSource(configuration, repository)
}

View File

@@ -1,24 +1,17 @@
package org.thoughtcrime.securesms.contacts.paged
import android.app.Application
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.mockkStatic
import io.mockk.verify
import io.reactivex.rxjava3.core.Single
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockedStatic
import org.mockito.internal.configuration.plugins.Plugins
import org.mockito.internal.junit.JUnitRule
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.any
import org.mockito.kotlin.argThat
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.core.util.logging.Log
@@ -29,6 +22,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabaseTestUtils
import org.thoughtcrime.securesms.database.model.IdentityRecord
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.testutil.MockAppDependenciesRule
import org.thoughtcrime.securesms.testutil.SystemOutLogger
import org.thoughtcrime.securesms.util.IdentityUtil
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException
@@ -39,26 +33,14 @@ import java.io.IOException
import java.util.Optional
import java.util.concurrent.TimeUnit
@Ignore
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class SafetyNumberRepositoryTest {
@get:Rule
val appDependencies = MockAppDependenciesRule()
@Rule
@JvmField
val mockitoRule: MockitoRule = JUnitRule(Plugins.getMockitoLogger(), Strictness.STRICT_STUBS)
@Mock
lateinit var profileService: ProfileService
@Mock(lenient = true)
lateinit var aciIdentityStore: SignalIdentityKeyStore
@Mock
lateinit var staticIdentityUtil: MockedStatic<IdentityUtil>
@Mock
lateinit var staticRecipient: MockedStatic<Recipient>
private val profileService = mockk<ProfileService>()
private val aciIdentityStore = mockk<SignalIdentityKeyStore>()
private var now: Long = System.currentTimeMillis()
@@ -77,6 +59,11 @@ class SafetyNumberRepositoryTest {
@Before
fun setUp() {
mockkStatic(IdentityUtil::class)
mockkObject(Recipient)
mockkStatic(Recipient::class)
now = System.currentTimeMillis()
repository = SafetyNumberRepository(profileService, aciIdentityStore)
@@ -85,7 +72,7 @@ class SafetyNumberRepositoryTest {
for (id in 1L until 12) {
val recipient = RecipientDatabaseTestUtils.createRecipient(resolved = true, recipientId = RecipientId.from(id))
staticRecipient.`when`<Recipient> { Recipient.resolved(RecipientId.from(id)) }.thenReturn(recipient)
every { Recipient.resolved(RecipientId.from(id)) } returns recipient
recipientPool.add(recipient)
val record = IdentityRecord(
@@ -96,11 +83,11 @@ class SafetyNumberRepositoryTest {
timestamp = 0,
nonblockingApproval = false
)
whenever(aciIdentityStore.getIdentityRecord(recipient.id)).thenReturn(Optional.of(record))
every { aciIdentityStore.getIdentityRecord(recipient.id) } returns Optional.of(record)
identityPool[recipient] = record
}
staticRecipient.`when`<Recipient> { Recipient.self() }.thenReturn(recipientPool[0])
every { Recipient.self() } returns recipientPool[0]
}
/**
@@ -111,13 +98,33 @@ class SafetyNumberRepositoryTest {
val other = recipientPool[1]
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf()), 200, "")))
every {
Recipient.resolvedList(
match { list ->
list.containsAll(
keys.map { key ->
key.recipientId
}
)
}
)
} returns listOf(other)
every {
profileService.performIdentityCheck(
mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)
)
} returns Single.just(
ServiceResponse.forResult(
IdentityCheckResponse(listOf()),
200,
""
)
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verifyNoInteractions()
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
/**
@@ -130,14 +137,27 @@ class SafetyNumberRepositoryTest {
val otherNewIdentityKey = IdentityKeyUtil.generateIdentityKeyPair().publicKey
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf(IdentityCheckResponse.ServiceIdentityPair(otherAci, otherNewIdentityKey))), 200, "")))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other)
every {
profileService.performIdentityCheck(
mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)
)
} returns Single.just(
ServiceResponse.forResult(
IdentityCheckResponse(
listOf(IdentityCheckResponse.ServiceIdentityPair(otherAci, otherNewIdentityKey))
),
200,
""
)
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verify { IdentityUtil.saveIdentity(otherAci.toString(), otherNewIdentityKey) }
staticIdentityUtil.verifyNoMoreInteractions()
verify { IdentityUtil.saveIdentity(otherAci.toString(), otherNewIdentityKey) }
}
/**
@@ -151,14 +171,30 @@ class SafetyNumberRepositoryTest {
val otherNewIdentityKey = IdentityKeyUtil.generateIdentityKeyPair().publicKey
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false), ContactSearchKey.RecipientSearchKey(secondOther.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other, secondOther))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey, secondOther.requireServiceId() to identityPool[secondOther]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf(IdentityCheckResponse.ServiceIdentityPair(otherAci, otherNewIdentityKey))), 200, "")))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other, secondOther)
every {
profileService.performIdentityCheck(
mapOf(
other.requireServiceId() to identityPool[other]!!.identityKey,
secondOther.requireServiceId() to identityPool[secondOther]!!.identityKey
)
)
} returns Single.just(
ServiceResponse.forResult(
IdentityCheckResponse(
listOf(IdentityCheckResponse.ServiceIdentityPair(otherAci, otherNewIdentityKey))
),
200,
""
)
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verify { IdentityUtil.saveIdentity(otherAci.toString(), otherNewIdentityKey) }
staticIdentityUtil.verifyNoMoreInteractions()
verify { IdentityUtil.saveIdentity(otherAci.toString(), otherNewIdentityKey) }
}
/**
@@ -169,18 +205,24 @@ class SafetyNumberRepositoryTest {
val other = recipientPool[1]
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf()), 200, "")))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other)
every {
profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey))
} returns Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf()), 200, ""))
repository.batchSafetyNumberCheckSync(keys, now)
verify(profileService, times(1)).performIdentityCheck(any())
repository.batchSafetyNumberCheckSync(keys, now + TimeUnit.SECONDS.toMillis(10))
verify(profileService, times(1)).performIdentityCheck(any())
repository.batchSafetyNumberCheckSync(keys, now + TimeUnit.SECONDS.toMillis(31))
verify(profileService, times(2)).performIdentityCheck(any())
verify(exactly = 1) { profileService.performIdentityCheck(any()) }
staticIdentityUtil.verifyNoInteractions()
repository.batchSafetyNumberCheckSync(keys, now + TimeUnit.SECONDS.toMillis(10))
verify(exactly = 1) { profileService.performIdentityCheck(any()) }
repository.batchSafetyNumberCheckSync(keys, now + TimeUnit.SECONDS.toMillis(31))
verify(exactly = 2) { profileService.performIdentityCheck(any()) }
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
/**
@@ -188,19 +230,22 @@ class SafetyNumberRepositoryTest {
*/
@Test
fun batchSafetyNumberCheckSync_batchOf10WithSmallBatchSize_noChanges() {
val keys = recipientPool.map { ContactSearchKey.RecipientSearchKey(it.id, false) }
val keys = recipientPool.map { receipient -> ContactSearchKey.RecipientSearchKey(receipient.id, false) }
val others = recipientPool.subList(1, recipientPool.lastIndex)
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(others.map { it.id }) }) }.thenReturn(others)
every {
Recipient.resolvedList(match { list -> list.containsAll(others.map { key -> key.id }) })
} returns others
for (chunk in others.chunked(2)) {
whenever(profileService.performIdentityCheck(chunk.associate { it.requireServiceId() to identityPool[it]!!.identityKey }))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf()), 200, "")))
every {
profileService.performIdentityCheck(any())
} answers {
Single.just(ServiceResponse.forResult(IdentityCheckResponse(listOf()), 200, ""))
}
repository.batchSafetyNumberCheckSync(keys, now, 2)
staticIdentityUtil.verifyNoInteractions()
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
@Test
@@ -208,13 +253,21 @@ class SafetyNumberRepositoryTest {
val other = recipientPool[1]
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forApplicationError(NonSuccessfulResponseCodeException(400), 400, "")))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other)
every {
profileService.performIdentityCheck(
mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)
)
} returns Single.just(
ServiceResponse.forApplicationError(NonSuccessfulResponseCodeException(400), 400, "")
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verifyNoInteractions()
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
@Test
@@ -222,13 +275,21 @@ class SafetyNumberRepositoryTest {
val other = recipientPool[1]
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forUnknownError(IOException())))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other)
every {
profileService.performIdentityCheck(
mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)
)
} returns Single.just(
ServiceResponse.forUnknownError(IOException())
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verifyNoInteractions()
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
@Test
@@ -236,12 +297,24 @@ class SafetyNumberRepositoryTest {
val other = recipientPool[1]
val keys = listOf(ContactSearchKey.RecipientSearchKey(other.id, false))
staticRecipient.`when`<List<Recipient>> { Recipient.resolvedList(argThat { containsAll(keys.map { it.recipientId }) }) }.thenReturn(listOf(other))
whenever(profileService.performIdentityCheck(mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)))
.thenReturn(Single.just(ServiceResponse.forResult(IdentityCheckResponse(), 200, "")))
every {
Recipient.resolvedList(match { list -> list.containsAll(keys.map { key -> key.recipientId }) })
} returns listOf(other)
every {
profileService.performIdentityCheck(
mapOf(other.requireServiceId() to identityPool[other]!!.identityKey)
)
} returns Single.just(
ServiceResponse.forResult(
IdentityCheckResponse(),
200,
""
)
)
repository.batchSafetyNumberCheckSync(keys, now)
staticIdentityUtil.verifyNoInteractions()
verify(exactly = 0) { IdentityUtil.saveIdentity(any(), any()) }
}
}