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

@ -1,25 +1,19 @@
package org.thoughtcrime.securesms.backup.v2
import org.junit.Before
import io.mockk.every
import io.mockk.mockk
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import org.thoughtcrime.securesms.MockCursor
import org.thoughtcrime.securesms.assertIsSize
class ArchivedMediaObjectIteratorTest {
private val cursor: MockCursor = mock()
@Before
fun setUp() {
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()
private val cursor = mockk<MockCursor>(relaxed = true) {
every { getString(any()) } returns "A"
every { moveToPosition(any()) } answers { callOriginal() }
every { moveToNext() } answers { callOriginal() }
every { position } answers { callOriginal() }
every { isLast } answers { callOriginal() }
every { isAfterLast } answers { callOriginal() }
}
@Test
@ -33,7 +27,7 @@ class ArchivedMediaObjectIteratorTest {
}
private fun runTest(size: Int) {
whenever(cursor.count).thenReturn(size)
every { cursor.count } returns size
val iterator = ArchivedMediaObjectIterator(cursor)
val list = iterator.asSequence().toList()

View file

@ -9,34 +9,29 @@ import androidx.media3.common.C
import androidx.media3.session.MediaSession
import androidx.media3.session.SessionCommand
import androidx.test.core.app.ApplicationProvider
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
class VoiceNotePlayerCallbackTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val mediaAudioAttributes = AudioAttributes.Builder().setContentType(C.AUDIO_CONTENT_TYPE_MUSIC).setUsage(C.USAGE_MEDIA).build()
private val callAudioAttributes = AudioAttributes.Builder().setContentType(C.AUDIO_CONTENT_TYPE_SPEECH).setUsage(C.USAGE_VOICE_COMMUNICATION).build()
private val session = mock(MediaSession::class.java)
private val controllerInfo = mock(MediaSession.ControllerInfo::class.java)
private val player: VoiceNotePlayer = mock(VoiceNotePlayer::class.java)
private val session = mockk<MediaSession>()
private val controllerInfo = mockk<MediaSession.ControllerInfo>()
private val player = mockk<VoiceNotePlayer>(relaxUnitFun = true)
private val testSubject = VoiceNotePlayerCallback(context, player)
@Test
fun `Given stream is media, When I onCommand for voice, then I expect the stream to switch to voice and continue playback`() {
// GIVEN
`when`(player.audioAttributes).thenReturn(mediaAudioAttributes)
every { player.audioAttributes } returns mediaAudioAttributes
val command = SessionCommand(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, Bundle.EMPTY)
val extras = Bundle().apply { putInt(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, AudioManager.STREAM_VOICE_CALL) }
@ -46,15 +41,15 @@ class VoiceNotePlayerCallbackTest {
testSubject.onCustomCommand(session, controllerInfo, command, extras)
// THEN
verify(player).playWhenReady = false
verify(player).setAudioAttributes(expected, false)
verify(player).playWhenReady = true
verify { player.playWhenReady = false }
verify { player.setAudioAttributes(expected, false) }
verify { player.playWhenReady = true }
}
@Test
fun `Given stream is voice, When I onCommand for media, then I expect the stream to switch to media and pause playback`() {
// GIVEN
`when`(player.audioAttributes).thenReturn(callAudioAttributes)
every { player.audioAttributes } returns callAudioAttributes
val command = SessionCommand(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, Bundle.EMPTY)
val extras = Bundle().apply { putInt(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, AudioManager.STREAM_MUSIC) }
@ -64,15 +59,15 @@ class VoiceNotePlayerCallbackTest {
testSubject.onCustomCommand(session, controllerInfo, command, extras)
// THEN
verify(player).playWhenReady = false
verify(player).setAudioAttributes(expected, true)
verify(player, Mockito.never()).playWhenReady = true
verify { player.playWhenReady = false }
verify { player.setAudioAttributes(expected, true) }
verify(exactly = 0) { player.playWhenReady = true }
}
@Test
fun `Given stream is voice, When I onCommand for voice, then I expect no change`() {
// GIVEN
`when`(player.audioAttributes).thenReturn(callAudioAttributes)
every { player.audioAttributes } returns callAudioAttributes
val command = SessionCommand(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, Bundle.EMPTY)
val extras = Bundle().apply { putInt(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, AudioManager.STREAM_VOICE_CALL) }
@ -81,14 +76,14 @@ class VoiceNotePlayerCallbackTest {
testSubject.onCustomCommand(session, controllerInfo, command, extras)
// THEN
verify(player, Mockito.never()).playWhenReady = anyBoolean()
verify(player, Mockito.never()).setAudioAttributes(any(), eq(false))
verify(exactly = 0) { player.playWhenReady = any() }
verify(exactly = 0) { player.setAudioAttributes(any(), false) }
}
@Test
fun `Given stream is media, When I onCommand for media, then I expect no change`() {
// GIVEN
`when`(player.audioAttributes).thenReturn(mediaAudioAttributes)
every { player.audioAttributes } returns mediaAudioAttributes
val command = SessionCommand(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, Bundle.EMPTY)
val extras = Bundle().apply { putInt(VoiceNotePlaybackService.ACTION_SET_AUDIO_STREAM, AudioManager.STREAM_MUSIC) }
@ -97,7 +92,7 @@ class VoiceNotePlayerCallbackTest {
testSubject.onCustomCommand(session, controllerInfo, command, extras)
// THEN
verify(player, Mockito.never()).playWhenReady = anyBoolean()
verify(player, Mockito.never()).setAudioAttributes(any(), anyBoolean())
verify(exactly = 0) { player.playWhenReady = any() }
verify(exactly = 0) { player.setAudioAttributes(any(), any()) }
}
}

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()) }
}
}

View file

@ -2,12 +2,13 @@ package org.thoughtcrime.securesms.conversation
import android.app.Application
import androidx.lifecycle.LifecycleOwner
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.verify
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.shadows.ShadowLooper
@ -16,9 +17,10 @@ import java.util.concurrent.TimeUnit
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
class ConversationUpdateTickTest {
private val lifecycleOwner = mock(LifecycleOwner::class.java)
private val listener = mock(ConversationUpdateTick.OnTickListener::class.java)
private val lifecycleOwner = mockk<LifecycleOwner>()
private val listener = mockk<ConversationUpdateTick.OnTickListener> {
every { onTick() } just runs
}
private val testSubject = ConversationUpdateTick(listener)
private val timeoutMillis = ConversationUpdateTick.TIMEOUT
@ -26,7 +28,7 @@ class ConversationUpdateTickTest {
@Test
fun `Given onResume not invoked, then I expect zero invocations of onTick`() {
// THEN
verify(listener, never()).onTick()
verify(exactly = 0) { listener.onTick() }
}
@Test
@ -36,7 +38,7 @@ class ConversationUpdateTickTest {
testSubject.onResume(lifecycleOwner)
// THEN
verify(listener, never()).onTick()
verify(exactly = 0) { listener.onTick() }
}
@Test
@ -46,7 +48,7 @@ class ConversationUpdateTickTest {
ShadowLooper.idleMainLooper(timeoutMillis / 2, TimeUnit.MILLISECONDS)
// THEN
verify(listener, never()).onTick()
verify(exactly = 0) { listener.onTick() }
}
@Test
@ -58,7 +60,7 @@ class ConversationUpdateTickTest {
ShadowLooper.idleMainLooper(timeoutMillis, TimeUnit.MILLISECONDS)
// THEN
verify(listener, times(1)).onTick()
verify(exactly = 1) { listener.onTick() }
}
@Test
@ -70,7 +72,7 @@ class ConversationUpdateTickTest {
ShadowLooper.idleMainLooper(timeoutMillis * 5, TimeUnit.MILLISECONDS)
// THEN
verify(listener, times(5)).onTick()
verify(exactly = 5) { listener.onTick() }
}
@Test
@ -83,6 +85,6 @@ class ConversationUpdateTickTest {
ShadowLooper.idleMainLooper(timeoutMillis, TimeUnit.MILLISECONDS)
// THEN
verify(listener, never()).onTick()
verify(exactly = 0) { listener.onTick() }
}
}

View file

@ -1,13 +1,12 @@
package org.thoughtcrime.securesms.crypto.storage
import android.content.Context
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.signal.libsignal.protocol.IdentityKey
import org.signal.libsignal.protocol.SignalProtocolAddress
import org.signal.libsignal.protocol.ecc.ECPublicKey
@ -16,7 +15,6 @@ import org.thoughtcrime.securesms.database.model.IdentityStoreRecord
import org.whispersystems.signalservice.test.LibSignalLibraryUtil.assumeLibSignalSupportedOnOS
class SignalBaseIdentityKeyStoreTest {
companion object {
private const val ADDRESS = "address1"
}
@ -28,36 +26,36 @@ class SignalBaseIdentityKeyStoreTest {
@Test
fun `getIdentity() hits disk on first retrieve but not the second`() {
val mockDb = mock(IdentityTable::class.java)
val subject = SignalBaseIdentityKeyStore(mock(Context::class.java), mockDb)
val mockDb = mockk<IdentityTable>()
val subject = SignalBaseIdentityKeyStore(mockk<Context>(), mockDb)
val identityKey = IdentityKey(ECPublicKey.fromPublicKeyBytes(ByteArray(32)))
val record = mockRecord(ADDRESS, identityKey)
`when`(mockDb.getIdentityStoreRecord(ADDRESS)).thenReturn(record)
every { mockDb.getIdentityStoreRecord(ADDRESS) } returns record
assertEquals(identityKey, subject.getIdentity(SignalProtocolAddress(ADDRESS, 1)))
verify(mockDb, times(1)).getIdentityStoreRecord(ADDRESS)
verify(exactly = 1) { mockDb.getIdentityStoreRecord(ADDRESS) }
assertEquals(identityKey, subject.getIdentity(SignalProtocolAddress(ADDRESS, 1)))
verify(mockDb, times(1)).getIdentityStoreRecord(ADDRESS)
verify(exactly = 1) { mockDb.getIdentityStoreRecord(ADDRESS) }
}
@Test
fun `invalidate() evicts cache entry`() {
val mockDb = mock(IdentityTable::class.java)
val subject = SignalBaseIdentityKeyStore(mock(Context::class.java), mockDb)
val mockDb = mockk<IdentityTable>()
val subject = SignalBaseIdentityKeyStore(mockk<Context>(), mockDb)
val identityKey = IdentityKey(ECPublicKey.fromPublicKeyBytes(ByteArray(32)))
val record = mockRecord(ADDRESS, identityKey)
`when`(mockDb.getIdentityStoreRecord(ADDRESS)).thenReturn(record)
every { mockDb.getIdentityStoreRecord(ADDRESS) } returns record
assertEquals(identityKey, subject.getIdentity(SignalProtocolAddress(ADDRESS, 1)))
verify(mockDb, times(1)).getIdentityStoreRecord(ADDRESS)
verify(exactly = 1) { mockDb.getIdentityStoreRecord(ADDRESS) }
subject.invalidate(ADDRESS)
assertEquals(identityKey, subject.getIdentity(SignalProtocolAddress(ADDRESS, 1)))
verify(mockDb, times(2)).getIdentityStoreRecord(ADDRESS)
verify(exactly = 2) { mockDb.getIdentityStoreRecord(ADDRESS) }
}
private fun mockRecord(addressName: String, identityKey: IdentityKey): IdentityStoreRecord {

View file

@ -1,30 +1,28 @@
package org.thoughtcrime.securesms.database.model
import io.mockk.every
import io.mockk.mockk
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.signal.core.util.Base64
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
import org.thoughtcrime.securesms.groups.v2.ChangeBuilder
import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.internal.push.GroupContextV2
import java.util.Random
import java.util.UUID
import kotlin.random.Random
@Suppress("ClassName")
class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
/**
* Given a non-gv2 message, when I append, then I expect an assertion error
*/
@Test(expected = AssertionError::class)
fun throwOnNonGv2() {
val messageRecord = mock<MessageRecord> {
on { decryptedGroupV2Context } doReturn null
val messageRecord = mockk<MessageRecord> {
every { decryptedGroupV2Context } returns null
}
MessageRecord.createNewContextWithAppendedDeleteJoinRequest(messageRecord, 0, ByteString.EMPTY)
@ -37,8 +35,8 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
fun throwOnEmptyGv2Change() {
val groupContext = DecryptedGroupV2Context()
val messageRecord = mock<MessageRecord> {
on { decryptedGroupV2Context } doReturn groupContext
val messageRecord = mockk<MessageRecord> {
every { decryptedGroupV2Context } returns groupContext
}
MessageRecord.createNewContextWithAppendedDeleteJoinRequest(messageRecord, 0, ByteString.EMPTY)
@ -59,26 +57,20 @@ class MessageRecordTest_createNewContextWithAppendedDeleteJoinRequest {
.build()
val context = DecryptedGroupV2Context.Builder()
.context(GroupContextV2.Builder().masterKey(randomBytes().toByteString()).build())
.context(GroupContextV2.Builder().masterKey(Random.nextBytes(32).toByteString()).build())
.change(change)
.build()
val messageRecord = mock<MessageRecord> {
on { decryptedGroupV2Context } doReturn context
val messageRecord = mockk<MessageRecord> {
every { decryptedGroupV2Context } returns context
}
val newEncodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(messageRecord, 10, aliceByteString)
val newContext = DecryptedGroupV2Context.ADAPTER.decode(Base64.decode(newEncodedBody))
assertThat("revision updated to 10", newContext.change!!.revision, `is`(10))
assertThat("change should retain join request", newContext.change!!.newRequestingMembers[0].aciBytes, `is`(aliceByteString))
assertThat("change should add delete request", newContext.change!!.deleteRequestingMembers[0], `is`(aliceByteString))
}
private fun randomBytes(): ByteArray {
val bytes = ByteArray(32)
Random().nextBytes(bytes)
return bytes
assertEquals("revision updated to 10", newContext.change?.revision, 10)
assertEquals("change should retain join request", newContext.change?.newRequestingMembers?.single()?.aciBytes, aliceByteString)
assertEquals("change should add delete request", newContext.change?.deleteRequestingMembers?.single(), aliceByteString)
}
}

View file

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.dependencies
import io.mockk.mockk
import org.mockito.Mockito
import org.signal.core.util.billing.BillingApi
import org.signal.core.util.concurrent.DeadlockDetector
import org.signal.libsignal.net.Network
@ -134,7 +133,7 @@ class MockApplicationDependencyProvider : AppDependencies.Provider {
}
override fun provideDatabaseObserver(): DatabaseObserver {
return Mockito.mock(DatabaseObserver::class.java)
return mockk(relaxed = true)
}
override fun providePayments(signalServiceAccountManager: SignalServiceAccountManager): Payments {

View file

@ -4,17 +4,12 @@ import android.app.Application
import android.content.Context
import android.net.Uri
import androidx.test.core.app.ApplicationProvider
import io.mockk.every
import io.mockk.mockkStatic
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.MockedStatic
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.core.util.logging.Log
@ -26,14 +21,6 @@ import java.util.Optional
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
class MediaRepositoryTest {
@Rule
@JvmField
val mockitoRule: MockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var staticMediaUtilMock: MockedStatic<MediaUtil>
private lateinit var context: Context
@Before
@ -41,7 +28,9 @@ class MediaRepositoryTest {
Log.initialize(EmptyLogger())
context = ApplicationProvider.getApplicationContext()
`when`(MediaUtil.isOctetStream(MediaUtil.OCTET)).thenReturn(true)
mockkStatic(MediaUtil::class)
every { MediaUtil.isOctetStream(MediaUtil.OCTET) } returns true
}
@Test
@ -62,7 +51,7 @@ class MediaRepositoryTest {
val media = buildMedia(mimeType = MediaUtil.OCTET)
// WHEN
`when`(MediaUtil.getMimeType(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(MediaUtil.IMAGE_JPEG)
every { MediaUtil.getMimeType(any(), any()) } returns MediaUtil.IMAGE_JPEG
val result: Media = MediaRepository.fixMimeType(context, media)
// THEN

View file

@ -1,48 +0,0 @@
package org.thoughtcrime.securesms.recipients
import android.app.Application
import androidx.test.core.app.ApplicationProvider
import org.junit.Before
import org.junit.Rule
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.MockedConstruction
import org.mockito.MockedStatic
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
abstract class BaseRecipientTest {
@Rule
@JvmField
val mockitoRule: MockitoRule = MockitoJUnit.rule()
@Mock
private lateinit var applicationDependenciesStaticMock: MockedStatic<AppDependencies>
@Mock
private lateinit var attachmentSecretProviderStaticMock: MockedStatic<AttachmentSecretProvider>
@Mock
private lateinit var signalStoreStaticMock: MockedStatic<SignalStore>
@Mock
private lateinit var mockedSignalStoreConstruction: MockedConstruction<SignalStore>
@Before
fun superSetUp() {
val application = ApplicationProvider.getApplicationContext<Application>()
`when`(AppDependencies.application).thenReturn(application)
`when`(AttachmentSecretProvider.getInstance(ArgumentMatchers.any())).thenThrow(RuntimeException::class.java)
}
}

View file

@ -1,25 +1,34 @@
package org.thoughtcrime.securesms.recipients
import android.app.Application
import android.graphics.Color
import androidx.test.core.app.ApplicationProvider
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.database.RecipientDatabaseTestUtils.createRecipient
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.keyvalue.ChatColorsValues
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.WallpaperValues
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
@Suppress("ClassName")
class Recipient_getChatColorsTest : BaseRecipientTest() {
@RunWith(RobolectricTestRunner::class)
@Config(manifest = Config.NONE, application = Application::class)
class Recipient_getChatColorsTest {
private val defaultChatColors = ChatColorsPalette.Bubbles.default.withId(ChatColors.Id.Auto)
private val globalWallpaperChatColor = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.RED)
private val globalChatColor = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.GREEN)
@ -29,6 +38,12 @@ class Recipient_getChatColorsTest : BaseRecipientTest() {
@Before
fun setUp() {
mockkStatic(AppDependencies::class)
every { AppDependencies.application } returns ApplicationProvider.getApplicationContext()
mockkStatic(AttachmentSecretProvider::class)
every { AttachmentSecretProvider.getInstance(any()) } throws RuntimeException("Whoa, nelly!")
wallpaperValues = mockk()
chatColorsValues = mockk()
@ -225,7 +240,7 @@ class Recipient_getChatColorsTest : BaseRecipientTest() {
private fun createWallpaper(
chatColors: ChatColors
): ChatWallpaper {
return mockk<ChatWallpaper>().apply {
return mockk<ChatWallpaper> {
every { autoChatColors } answers { chatColors }
}
}