Skip to content

Commit e070c5d

Browse files
authored
Fix unit tests (#5947)
* move createLocale() method to companion object and add test dependency * use mockk() from Mockk library for mocking sealed classes * change method parameter to null-able String type * add null check for accessing property from unit tests * change method signature to match old method's signature It fixes the NullPointerException when running ImageProcessingUnitTest * Fix unresolved references and make properties public for unit tests * fix tests in UploadRepositoryUnitTest by making return type null-able
1 parent fe347c2 commit e070c5d

File tree

14 files changed

+56
-52
lines changed

14 files changed

+56
-52
lines changed

app/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ dependencies {
9898
testImplementation 'org.mockito:mockito-core:5.6.0'
9999
testImplementation "org.powermock:powermock-module-junit4:2.0.9"
100100
testImplementation "org.powermock:powermock-api-mockito2:2.0.9"
101+
testImplementation("io.mockk:mockk:1.13.5")
101102

102103
// Unit testing
103104
testImplementation 'junit:junit:4.13.2'

app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ class CategoryClient
124124
}.map {
125125
it
126126
.filter { page ->
127-
!page.categoryInfo().isHidden
127+
// Null check is not redundant because some values could be null
128+
// for mocks when running unit tests
129+
page.categoryInfo()?.isHidden != true
128130
}.map {
129131
CategoryItem(
130132
it.title().replace(CATEGORY_PREFIX, ""),

app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesDao.kt

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import android.content.ContentValues
66
import android.database.Cursor
77
import android.database.sqlite.SQLiteDatabase
88
import android.os.RemoteException
9-
import java.util.ArrayList
109
import javax.inject.Inject
1110
import javax.inject.Named
1211
import javax.inject.Provider
@@ -163,9 +162,9 @@ class RecentLanguagesDao @Inject constructor(
163162
COLUMN_CODE
164163
)
165164

166-
private const val DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS $TABLE_NAME"
165+
const val DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS $TABLE_NAME"
167166

168-
private const val CREATE_TABLE_STATEMENT = "CREATE TABLE $TABLE_NAME (" +
167+
const val CREATE_TABLE_STATEMENT = "CREATE TABLE $TABLE_NAME (" +
169168
"$COLUMN_NAME STRING," +
170169
"$COLUMN_CODE STRING PRIMARY KEY" +
171170
");"

app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt

+8-8
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
1919
import io.reactivex.Flowable
2020
import io.reactivex.Observable
2121
import io.reactivex.Single
22+
import timber.log.Timber
2223
import java.util.Locale
2324
import javax.inject.Inject
2425
import javax.inject.Singleton
25-
import timber.log.Timber
2626

2727
/**
2828
* The repository class for UploadActivity
@@ -46,7 +46,7 @@ class UploadRepository @Inject constructor(
4646
*
4747
* @return
4848
*/
49-
fun buildContributions(): Observable<Contribution> {
49+
fun buildContributions(): Observable<Contribution>? {
5050
return uploadModel.buildContributions()
5151
}
5252

@@ -150,7 +150,7 @@ class UploadRepository @Inject constructor(
150150
*
151151
* @return
152152
*/
153-
fun getSelectedLicense(): String {
153+
fun getSelectedLicense(): String? {
154154
return uploadModel.selectedLicense
155155
}
156156

@@ -173,11 +173,11 @@ class UploadRepository @Inject constructor(
173173
* @return
174174
*/
175175
fun preProcessImage(
176-
uploadableFile: UploadableFile,
176+
uploadableFile: UploadableFile?,
177177
place: Place?,
178-
similarImageInterface: SimilarImageInterface,
178+
similarImageInterface: SimilarImageInterface?,
179179
inAppPictureLocation: LatLng?
180-
): Observable<UploadItem> {
180+
): Observable<UploadItem>? {
181181
return uploadModel.preProcessImage(
182182
uploadableFile,
183183
place,
@@ -193,7 +193,7 @@ class UploadRepository @Inject constructor(
193193
* @param location Location of the image
194194
* @return Quality of UploadItem
195195
*/
196-
fun getImageQuality(uploadItem: UploadItem, location: LatLng?): Single<Int> {
196+
fun getImageQuality(uploadItem: UploadItem, location: LatLng?): Single<Int>? {
197197
return uploadModel.getImageQuality(uploadItem, location)
198198
}
199199

@@ -213,7 +213,7 @@ class UploadRepository @Inject constructor(
213213
* @param uploadItem UploadItem whose caption is to be checked
214214
* @return Quality of caption of the UploadItem
215215
*/
216-
fun getCaptionQuality(uploadItem: UploadItem): Single<Int> {
216+
fun getCaptionQuality(uploadItem: UploadItem): Single<Int>? {
217217
return uploadModel.getCaptionQuality(uploadItem)
218218
}
219219

app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt

+14-12
Original file line numberDiff line numberDiff line change
@@ -471,18 +471,20 @@ class SettingsFragment : PreferenceFragmentCompat() {
471471
editor.apply()
472472
}
473473

474-
/**
475-
* Create Locale based on different types of language codes
476-
* @param languageCode
477-
* @return Locale and throws error for invalid language codes
478-
*/
479-
fun createLocale(languageCode: String): Locale {
480-
val parts = languageCode.split("-")
481-
return when (parts.size) {
482-
1 -> Locale(parts[0])
483-
2 -> Locale(parts[0], parts[1])
484-
3 -> Locale(parts[0], parts[1], parts[2])
485-
else -> throw IllegalArgumentException("Invalid language code: $languageCode")
474+
companion object {
475+
/**
476+
* Create Locale based on different types of language codes
477+
* @param languageCode
478+
* @return Locale and throws error for invalid language codes
479+
*/
480+
fun createLocale(languageCode: String): Locale {
481+
val parts = languageCode.split("-")
482+
return when (parts.size) {
483+
1 -> Locale(parts[0])
484+
2 -> Locale(parts[0], parts[1])
485+
3 -> Locale(parts[0], parts[1], parts[2])
486+
else -> throw IllegalArgumentException("Invalid language code: $languageCode")
487+
}
486488
}
487489
}
488490

app/src/main/java/fr/free/nrw/commons/utils/ImageUtilsWrapper.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ImageUtilsWrapper @Inject constructor() {
1616

1717
fun checkImageGeolocationIsDifferent(
1818
geolocationOfFileString: String,
19-
latLng: LatLng
19+
latLng: LatLng?
2020
): Single<Int> {
2121
return Single.fromCallable {
2222
ImageUtils.checkImageGeolocationIsDifferent(geolocationOfFileString, latLng)

app/src/main/java/fr/free/nrw/commons/utils/MediaDataExtractorUtil.kt

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package fr.free.nrw.commons.utils
22

3-
import org.apache.commons.lang3.StringUtils
4-
5-
import java.util.ArrayList
6-
73
object MediaDataExtractorUtil {
84

95
/**
@@ -13,8 +9,8 @@ object MediaDataExtractorUtil {
139
* @return
1410
*/
1511
@JvmStatic
16-
fun extractCategoriesFromList(source: String): List<String> {
17-
if (source.isBlank()) {
12+
fun extractCategoriesFromList(source: String?): List<String> {
13+
if (source.isNullOrBlank()) {
1814
return emptyList()
1915
}
2016
val cats = source.split("|")

app/src/test/kotlin/fr/free/nrw/commons/auth/LoginActivityUnitTests.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import fr.free.nrw.commons.TestCommonsApplication
1616
import fr.free.nrw.commons.auth.login.LoginResult
1717
import fr.free.nrw.commons.createTestClient
1818
import fr.free.nrw.commons.kvstore.JsonKvStore
19+
import io.mockk.mockk
1920
import org.junit.Assert
2021
import org.junit.Before
2122
import org.junit.Test
@@ -66,11 +67,11 @@ class LoginActivityUnitTests {
6667
@Mock
6768
private lateinit var account: Account
6869

69-
@Mock
7070
private lateinit var loginResult: LoginResult
7171

7272
@Before
7373
fun setUp() {
74+
loginResult = mockk()
7475
MockitoAnnotations.openMocks(this)
7576
OkHttpConnectionFactory.CLIENT = createTestClient()
7677
activity = Robolectric.buildActivity(LoginActivity::class.java).create().get()

app/src/test/kotlin/fr/free/nrw/commons/auth/SessionManagerUnitTests.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import androidx.test.core.app.ApplicationProvider
77
import fr.free.nrw.commons.TestCommonsApplication
88
import fr.free.nrw.commons.auth.login.LoginResult
99
import fr.free.nrw.commons.kvstore.JsonKvStore
10+
import io.mockk.every
11+
import io.mockk.mockk
1012
import org.junit.Assert
1113
import org.junit.Before
1214
import org.junit.Test
1315
import org.junit.runner.RunWith
1416
import org.mockito.Mock
1517
import org.mockito.MockitoAnnotations
16-
import org.powermock.api.mockito.PowerMockito.`when`
1718
import org.robolectric.RobolectricTestRunner
1819
import org.robolectric.Shadows.shadowOf
1920
import org.robolectric.annotation.Config
@@ -33,14 +34,14 @@ class SessionManagerUnitTests {
3334
@Mock
3435
private lateinit var defaultKvStore: JsonKvStore
3536

36-
@Mock
3737
private lateinit var loginResult: LoginResult
3838

3939
@Mock
4040
private lateinit var context: Context
4141

4242
@Before
4343
fun setUp() {
44+
loginResult = mockk()
4445
MockitoAnnotations.openMocks(this)
4546
accountManager = AccountManager.get(ApplicationProvider.getApplicationContext())
4647
shadowOf(accountManager).addAccount(account)
@@ -68,8 +69,8 @@ class SessionManagerUnitTests {
6869
@Test
6970
@Throws(Exception::class)
7071
fun testUpdateAccount() {
71-
`when`(loginResult.userName).thenReturn("username")
72-
`when`(loginResult.password).thenReturn("password")
72+
every { loginResult.userName } returns "username"
73+
every { loginResult.password } returns "password"
7374
val method: Method =
7475
SessionManager::class.java.getDeclaredMethod(
7576
"updateAccount",

app/src/test/kotlin/fr/free/nrw/commons/recentlanguages/RecentLanguagesDaoUnitTest.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class RecentLanguagesDaoUnitTest {
8585
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull()))
8686
.thenReturn(createCursor(14))
8787

88-
val result = testObject.recentLanguages
88+
val result = testObject.getRecentLanguages()
8989

9090
Assert.assertEquals(14, (result.size))
9191
}
@@ -95,20 +95,20 @@ class RecentLanguagesDaoUnitTest {
9595
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenThrow(
9696
RemoteException(""),
9797
)
98-
testObject.recentLanguages
98+
testObject.getRecentLanguages()
9999
}
100100

101101
@Test
102102
fun getGetRecentLanguagesReturnsEmptyList_emptyCursor() {
103103
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull()))
104104
.thenReturn(createCursor(0))
105-
Assert.assertTrue(testObject.recentLanguages.isEmpty())
105+
Assert.assertTrue(testObject.getRecentLanguages().isEmpty())
106106
}
107107

108108
@Test
109109
fun getGetRecentLanguagesReturnsEmptyList_nullCursor() {
110110
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenReturn(null)
111-
Assert.assertTrue(testObject.recentLanguages.isEmpty())
111+
Assert.assertTrue(testObject.getRecentLanguages().isEmpty())
112112
}
113113

114114
@Test
@@ -117,7 +117,7 @@ class RecentLanguagesDaoUnitTest {
117117
whenever(client.query(any(), any(), anyOrNull(), any(), anyOrNull())).thenReturn(mockCursor)
118118
whenever(mockCursor.moveToFirst()).thenReturn(false)
119119

120-
testObject.recentLanguages
120+
testObject.getRecentLanguages()
121121

122122
verify(mockCursor).close()
123123
}

app/src/test/kotlin/fr/free/nrw/commons/settings/SettingsFragmentUnitTests.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import fr.free.nrw.commons.TestCommonsApplication
1919
import fr.free.nrw.commons.recentlanguages.Language
2020
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter
2121
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao
22-
import fr.free.nrw.commons.settings.SettingsFragment.createLocale
22+
import fr.free.nrw.commons.settings.SettingsFragment.Companion.createLocale
2323
import org.junit.Assert
2424
import org.junit.Assert.assertEquals
2525
import org.junit.Before
@@ -156,14 +156,14 @@ class SettingsFragmentUnitTests {
156156
)
157157
method.isAccessible = true
158158
method.invoke(fragment, "appUiDefaultLanguagePref")
159-
verify(recentLanguagesDao, times(1)).recentLanguages
159+
verify(recentLanguagesDao, times(1)).getRecentLanguages()
160160
}
161161

162162
@Test
163163
@Throws(Exception::class)
164164
fun `Test prepareAppLanguages when recently used languages is not empty`() {
165165
Shadows.shadowOf(Looper.getMainLooper()).idle()
166-
whenever(recentLanguagesDao.recentLanguages)
166+
whenever(recentLanguagesDao.getRecentLanguages())
167167
.thenReturn(
168168
mutableListOf(
169169
Language("English", "en"),
@@ -181,7 +181,7 @@ class SettingsFragmentUnitTests {
181181
)
182182
method.isAccessible = true
183183
method.invoke(fragment, "appUiDefaultLanguagePref")
184-
verify(recentLanguagesDao, times(2)).recentLanguages
184+
verify(recentLanguagesDao, times(2)).getRecentLanguages()
185185
}
186186

187187
@Test

app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class UploadMediaPresenterTest {
131131
*/
132132
@Test
133133
fun getImageQualityTest() {
134-
whenever(repository.uploads).thenReturn(listOf(uploadItem))
134+
whenever(repository.getUploads()).thenReturn(listOf(uploadItem))
135135
whenever(repository.getImageQuality(uploadItem, location))
136136
.thenReturn(testSingleImageResult)
137137
whenever(uploadItem.imageQuality).thenReturn(0)
@@ -149,7 +149,7 @@ class UploadMediaPresenterTest {
149149
*/
150150
@Test
151151
fun `get ImageQuality Test while coordinates equals to null`() {
152-
whenever(repository.uploads).thenReturn(listOf(uploadItem))
152+
whenever(repository.getUploads()).thenReturn(listOf(uploadItem))
153153
whenever(repository.getImageQuality(uploadItem, location))
154154
.thenReturn(testSingleImageResult)
155155
whenever(uploadItem.imageQuality).thenReturn(0)
@@ -225,7 +225,7 @@ class UploadMediaPresenterTest {
225225
*/
226226
@Test
227227
fun fetchImageAndTitleTest() {
228-
whenever(repository.uploads).thenReturn(listOf(uploadItem))
228+
whenever(repository.getUploads()).thenReturn(listOf(uploadItem))
229229
whenever(repository.getUploadItem(ArgumentMatchers.anyInt()))
230230
.thenReturn(uploadItem)
231231
whenever(uploadItem.uploadMediaDetails).thenReturn(listOf())

app/src/test/kotlin/fr/free/nrw/commons/upload/UploadRepositoryUnitTest.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import fr.free.nrw.commons.repository.UploadRepository
1515
import fr.free.nrw.commons.upload.structure.depictions.DepictModel
1616
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
1717
import io.reactivex.Completable
18+
import io.reactivex.Observable
1819
import io.reactivex.Single
1920
import org.junit.Before
2021
import org.junit.Test
@@ -196,7 +197,7 @@ class UploadRepositoryUnitTest {
196197
fun testGetCaptionQuality() {
197198
assertEquals(
198199
repository.getCaptionQuality(uploadItem),
199-
uploadModel.getCaptionQuality(uploadItem),
200+
uploadModel.getCaptionQuality(uploadItem)
200201
)
201202
}
202203

@@ -386,7 +387,8 @@ class UploadRepositoryUnitTest {
386387
fun testGetCategories() {
387388
assertEquals(
388389
repository.getCategories(listOf("Test")),
389-
categoriesModel.getCategoriesByName(mutableListOf("Test")),
390+
categoriesModel.getCategoriesByName(mutableListOf("Test"))
391+
?: Observable.empty<List<CategoryItem>>()
390392
)
391393
}
392394
}

app/src/test/kotlin/fr/free/nrw/commons/upload/structure/depictions/DepictedItemTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package fr.free.nrw.commons.upload.structure.depictions
22

3-
import com.nhaarman.mockitokotlin2.mock
43
import depictedItem
54
import entity
65
import entityId
76
import fr.free.nrw.commons.wikidata.WikidataProperties
7+
import io.mockk.mockk
88
import org.junit.Assert
99
import org.junit.Test
1010
import place
@@ -53,7 +53,7 @@ class DepictedItemTest {
5353
entity(
5454
statements =
5555
mapOf(
56-
WikidataProperties.IMAGE.propertyName to listOf(statement(snak(dataValue = mock()))),
56+
WikidataProperties.IMAGE.propertyName to listOf(statement(snak(dataValue = mockk()))),
5757
),
5858
),
5959
).imageUrl,

0 commit comments

Comments
 (0)