Skip to content

Commit 2702ba7

Browse files
committed
Add tests
1 parent a03ad75 commit 2702ba7

File tree

2 files changed

+215
-2
lines changed

2 files changed

+215
-2
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/*
2+
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
3+
*/
4+
5+
package at.bitfire.davdroid.repository
6+
7+
import android.accounts.Account
8+
import android.accounts.AccountManager
9+
import android.content.Context
10+
import androidx.hilt.work.HiltWorkerFactory
11+
import at.bitfire.davdroid.R
12+
import at.bitfire.davdroid.TestUtils
13+
import at.bitfire.davdroid.resource.LocalAddressBookStore
14+
import at.bitfire.davdroid.resource.LocalCalendarStore
15+
import at.bitfire.davdroid.resource.LocalDataStore
16+
import at.bitfire.davdroid.settings.AccountSettings
17+
import at.bitfire.davdroid.sync.AutomaticSyncManager
18+
import at.bitfire.davdroid.sync.SyncDataType
19+
import at.bitfire.davdroid.sync.TasksAppManager
20+
import at.bitfire.davdroid.sync.account.AccountsCleanupWorker
21+
import at.bitfire.davdroid.sync.account.TestAccount
22+
import at.bitfire.davdroid.sync.worker.SyncWorkerManager
23+
import dagger.hilt.android.qualifiers.ApplicationContext
24+
import dagger.hilt.android.testing.BindValue
25+
import dagger.hilt.android.testing.HiltAndroidRule
26+
import dagger.hilt.android.testing.HiltAndroidTest
27+
import io.mockk.clearAllMocks
28+
import io.mockk.coVerify
29+
import io.mockk.every
30+
import io.mockk.impl.annotations.MockK
31+
import io.mockk.junit4.MockKRule
32+
import io.mockk.mockk
33+
import io.mockk.mockkObject
34+
import io.mockk.unmockkObject
35+
import io.mockk.verify
36+
import junit.framework.TestCase.assertTrue
37+
import kotlinx.coroutines.test.runTest
38+
import org.junit.After
39+
import org.junit.Before
40+
import org.junit.Rule
41+
import org.junit.Test
42+
import javax.inject.Inject
43+
44+
@HiltAndroidTest
45+
class AccountRepositoryTest {
46+
47+
@get:Rule
48+
val hiltRule = HiltAndroidRule(this)
49+
50+
@get:Rule
51+
val mockKRule = MockKRule(this)
52+
53+
// System under test
54+
55+
@Inject
56+
lateinit var accountRepository: AccountRepository
57+
58+
// Real injections
59+
60+
@Inject
61+
@ApplicationContext
62+
lateinit var context: Context
63+
64+
@Inject
65+
lateinit var accountSettingsFactory: AccountSettings.Factory
66+
67+
@Inject
68+
lateinit var workerFactory: HiltWorkerFactory
69+
70+
// Dependency overrides
71+
72+
@BindValue @MockK(relaxed = true)
73+
lateinit var automaticSyncManager: AutomaticSyncManager
74+
75+
@BindValue @MockK(relaxed = true)
76+
lateinit var localAddressBookStore: LocalAddressBookStore
77+
78+
@BindValue @MockK(relaxed = true)
79+
lateinit var localCalendarStore: LocalCalendarStore
80+
81+
@BindValue @MockK(relaxed = true)
82+
lateinit var serviceRepository: DavServiceRepository
83+
84+
@BindValue @MockK(relaxed = true)
85+
lateinit var syncWorkerManager: SyncWorkerManager
86+
87+
@BindValue @MockK(relaxed = true)
88+
lateinit var tasksAppManager: TasksAppManager
89+
90+
91+
// Account setup
92+
private val newName = "Renamed Account"
93+
lateinit var am: AccountManager
94+
lateinit var accountType: String
95+
lateinit var account: Account
96+
97+
@Before
98+
fun setUp() {
99+
hiltRule.inject()
100+
TestUtils.setUpWorkManager(context, workerFactory)
101+
102+
// Account setup
103+
am = AccountManager.get(context)
104+
accountType = context.getString(R.string.account_type)
105+
account = TestAccount.create()
106+
107+
// AccountsCleanupWorker static mocking
108+
mockkObject(AccountsCleanupWorker)
109+
every { AccountsCleanupWorker.lockAccountsCleanup() } returns Unit
110+
}
111+
112+
@After
113+
fun tearDown() {
114+
am.getAccountsByType(accountType).forEach { account ->
115+
am.removeAccountExplicitly(account)
116+
}
117+
118+
unmockkObject(AccountsCleanupWorker)
119+
clearAllMocks()
120+
}
121+
122+
123+
// testRename
124+
125+
@Test(expected = IllegalArgumentException::class)
126+
fun testRename_checksForAlreadyExisting() = runTest {
127+
val existing = Account("Existing Account", accountType)
128+
am.addAccountExplicitly(existing, null, null)
129+
130+
accountRepository.rename(account.name, existing.name)
131+
}
132+
133+
@Test
134+
fun testRename_locksAccountsCleanup() = runTest {
135+
accountRepository.rename(account.name, newName)
136+
137+
verify { AccountsCleanupWorker.lockAccountsCleanup() }
138+
}
139+
140+
@Test
141+
fun testRename_renamesAccountInAndroid() = runTest {
142+
accountRepository.rename(account.name, newName)
143+
144+
val accountsAfter = am.getAccountsByType(accountType)
145+
assertTrue(accountsAfter.any { it.name == newName })
146+
}
147+
148+
@Test
149+
fun testRename_cancelsRunningSynchronizationOfOldAccount() = runTest {
150+
accountRepository.rename(account.name, newName)
151+
152+
coVerify { syncWorkerManager.cancelAllWork(account) }
153+
}
154+
155+
@Test
156+
fun testRename_disablesPeriodicSyncsForOldAccount() = runTest {
157+
accountRepository.rename(account.name, newName)
158+
159+
for (dataType in SyncDataType.entries)
160+
coVerify(exactly = 1) {
161+
syncWorkerManager.disablePeriodic(account, dataType)
162+
}
163+
}
164+
165+
@Test
166+
fun testRename_updatesAccountNameReferencesInDatabase() = runTest {
167+
accountRepository.rename(account.name, newName)
168+
169+
coVerify { serviceRepository.renameAccount(account.name, newName) }
170+
}
171+
172+
@Test
173+
fun testRename_updatesAddressBooks() = runTest {
174+
accountRepository.rename(account.name, newName)
175+
176+
val newAccount = accountRepository.fromName(newName)
177+
coVerify { localAddressBookStore.updateAccount(account, newAccount) }
178+
}
179+
180+
@Test
181+
fun testRename_updatesCalendarEvents() = runTest {
182+
accountRepository.rename(account.name, newName)
183+
184+
val newAccount = accountRepository.fromName(newName)
185+
coVerify { localCalendarStore.updateAccount(account, newAccount) }
186+
}
187+
188+
@Test
189+
fun testRename_updatesAccountNameOfLocalTasks() = runTest {
190+
val mockDataStore = mockk<LocalDataStore<*>>(relaxed = true)
191+
every { tasksAppManager.getDataStore() } returns mockDataStore
192+
accountRepository.rename(account.name, newName)
193+
194+
coVerify { mockDataStore.updateAccount(account, accountRepository.fromName(newName)) }
195+
}
196+
197+
@Test
198+
fun testRename_updatesAutomaticSync() = runTest {
199+
accountRepository.rename(account.name, newName)
200+
201+
val newAccount = accountRepository.fromName(newName)
202+
coVerify { automaticSyncManager.updateAutomaticSync(newAccount) }
203+
}
204+
205+
@Test
206+
fun testRename_releasesAccountsCleanupWorkerMutex() = runTest {
207+
accountRepository.rename(account.name, newName)
208+
209+
verify { AccountsCleanupWorker.lockAccountsCleanup() }
210+
coVerify { serviceRepository.renameAccount(account.name, newName) }
211+
}
212+
213+
}

app/src/androidTest/kotlin/at/bitfire/davdroid/sync/account/TestAccount.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ object TestAccount {
1919
*
2020
* Remove it with [remove].
2121
*/
22-
fun create(version: Int = AccountSettings.CURRENT_VERSION): Account {
22+
fun create(version: Int = AccountSettings.CURRENT_VERSION, accountName: String = "Test Account"): Account {
2323
val accountType = targetContext.getString(R.string.account_type)
24-
val account = Account("Test Account", accountType)
24+
val account = Account(accountName, accountType)
2525

2626
val initialData = AccountSettings.initialUserData(null)
2727
initialData.putString(AccountSettings.KEY_SETTINGS_VERSION, version.toString())

0 commit comments

Comments
 (0)