mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-24 05:04:50 -04:00
#1174 Introduce Unit Testing - example of unit testing of a viewmodel
This commit is contained in:
parent
fcac33cf2d
commit
9e3bbe58ba
@ -136,6 +136,14 @@ dependencies {
|
|||||||
implementation "android.arch.lifecycle:extensions:1.1.1"
|
implementation "android.arch.lifecycle:extensions:1.1.1"
|
||||||
implementation "io.objectbox:objectbox-kotlin:$objectboxVersion"
|
implementation "io.objectbox:objectbox-kotlin:$objectboxVersion"
|
||||||
implementation "io.objectbox:objectbox-rxjava:$objectboxVersion"
|
implementation "io.objectbox:objectbox-rxjava:$objectboxVersion"
|
||||||
|
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter:5.4.2"
|
||||||
|
testImplementation "io.mockk:mockk:1.9"
|
||||||
|
testImplementation "org.assertj:assertj-core:3.11.1"
|
||||||
|
//update this with androidx
|
||||||
|
testImplementation 'com.jraska.livedata:testing-ktx:0.2.1'
|
||||||
|
testImplementation 'android.arch.core:core-testing:1.1.1'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set custom app import directory
|
// Set custom app import directory
|
||||||
@ -364,6 +372,9 @@ android {
|
|||||||
androidExtensions {
|
androidExtensions {
|
||||||
experimental = true
|
experimental = true
|
||||||
}
|
}
|
||||||
|
testOptions {
|
||||||
|
unitTests.returnDefaultValues = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testdroid deployment configuration
|
// Testdroid deployment configuration
|
||||||
|
@ -25,6 +25,7 @@ import dagger.Module;
|
|||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import dagger.android.AndroidInjectionModule;
|
import dagger.android.AndroidInjectionModule;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.UriToFileConverter;
|
||||||
import org.kiwix.kiwixmobile.utils.BookUtils;
|
import org.kiwix.kiwixmobile.utils.BookUtils;
|
||||||
|
|
||||||
@Module(includes = {
|
@Module(includes = {
|
||||||
@ -52,4 +53,9 @@ public class ApplicationModule {
|
|||||||
BookUtils provideBookUtils() {
|
BookUtils provideBookUtils() {
|
||||||
return new BookUtils();
|
return new BookUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides @Singleton
|
||||||
|
UriToFileConverter provideUriToFIleCOnverter() {
|
||||||
|
return new UriToFileConverter.Impl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import java.io.File
|
|||||||
|
|
||||||
data class BookOnDisk(
|
data class BookOnDisk(
|
||||||
val databaseId: Long? = null,
|
val databaseId: Long? = null,
|
||||||
val book: Book,
|
val book: Book = Book().apply { id = "" },
|
||||||
val file: File
|
val file: File = File("")
|
||||||
) {
|
) {
|
||||||
constructor(bookOnDiskEntity: BookOnDiskEntity) : this(
|
constructor(bookOnDiskEntity: BookOnDiskEntity) : this(
|
||||||
bookOnDiskEntity.id,
|
bookOnDiskEntity.id,
|
||||||
|
@ -17,12 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.downloader.model
|
package org.kiwix.kiwixmobile.downloader.model
|
||||||
|
|
||||||
import android.view.WindowId
|
|
||||||
import org.kiwix.kiwixmobile.database.newdb.entities.DownloadEntity
|
|
||||||
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity
|
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity
|
||||||
|
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
|
||||||
|
|
||||||
data class DownloadModel(
|
data class DownloadModel(
|
||||||
val databaseId: Long? = null,
|
val databaseId: Long? = null,
|
||||||
val downloadId: Long,
|
val downloadId: Long = 0,
|
||||||
val book: LibraryNetworkEntity.Book
|
val book: LibraryNetworkEntity.Book = Book().apply { id = "" }
|
||||||
)
|
)
|
||||||
|
@ -55,21 +55,22 @@ import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class DownloadStatus(
|
class DownloadStatus(
|
||||||
val downloadId: Long,
|
val downloadId: Long = 0L,
|
||||||
val title: String,
|
val title: String = "",
|
||||||
val description: String,
|
val description: String = "",
|
||||||
val state: DownloadState,
|
val state: DownloadState = DownloadState.Pending,
|
||||||
val bytesDownloadedSoFar: Long,
|
val bytesDownloadedSoFar: Long = 0,
|
||||||
val totalSizeBytes: Long,
|
val totalSizeBytes: Long = 0,
|
||||||
val lastModified: String,
|
val lastModified: String = "",
|
||||||
val localUri: String?,
|
val localUri: String? = null,
|
||||||
val mediaProviderUri: String?,
|
val mediaProviderUri: String? = null,
|
||||||
val mediaType: String?,
|
val mediaType: String? = null,
|
||||||
val uri: String?,
|
val uri: String? = null,
|
||||||
val book: Book
|
val book: Book = Book().apply { id = "" }
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toBookOnDisk() = BookOnDisk(book = book, file = File(Uri.parse(localUri).path))
|
fun toBookOnDisk(uriToFileConverter:UriToFileConverter) =
|
||||||
|
BookOnDisk(book = book, file = uriToFileConverter.convert(localUri))
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
@ -90,6 +91,11 @@ class DownloadStatus(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UriToFileConverter {
|
||||||
|
fun convert(uriString: String?) = File(Uri.parse(uriString).path)
|
||||||
|
class Impl:UriToFileConverter{}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class DownloadState(val stringId: Int) {
|
sealed class DownloadState(val stringId: Int) {
|
||||||
companion object {
|
companion object {
|
||||||
fun from(
|
fun from(
|
||||||
|
@ -3,8 +3,8 @@ package org.kiwix.kiwixmobile.zim_manager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.processors.BehaviorProcessor
|
import io.reactivex.processors.BehaviorProcessor
|
||||||
import io.reactivex.processors.PublishProcessor
|
|
||||||
import org.kiwix.kiwixmobile.extensions.networkState
|
import org.kiwix.kiwixmobile.extensions.networkState
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -13,14 +13,14 @@ class ConnectivityBroadcastReceiver @Inject constructor(private val connectivity
|
|||||||
|
|
||||||
override val action: String = ConnectivityManager.CONNECTIVITY_ACTION
|
override val action: String = ConnectivityManager.CONNECTIVITY_ACTION
|
||||||
|
|
||||||
val networkStates =
|
private val _networkStates = BehaviorProcessor.createDefault(connectivityManager.networkState)
|
||||||
BehaviorProcessor.createDefault(connectivityManager.networkState)
|
val networkStates: Flowable<NetworkState> = _networkStates
|
||||||
|
|
||||||
override fun onIntentWithActionReceived(
|
override fun onIntentWithActionReceived(
|
||||||
context: Context,
|
context: Context,
|
||||||
intent: Intent
|
intent: Intent
|
||||||
) {
|
) {
|
||||||
networkStates.onNext(connectivityManager.networkState)
|
_networkStates.onNext(connectivityManager.networkState)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -21,6 +21,7 @@ package org.kiwix.kiwixmobile.zim_manager
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.arch.lifecycle.MutableLiveData
|
import android.arch.lifecycle.MutableLiveData
|
||||||
import android.arch.lifecycle.ViewModel
|
import android.arch.lifecycle.ViewModel
|
||||||
|
import android.support.annotation.VisibleForTesting
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@ -39,6 +40,7 @@ import org.kiwix.kiwixmobile.downloader.model.DownloadItem
|
|||||||
import org.kiwix.kiwixmobile.downloader.model.DownloadModel
|
import org.kiwix.kiwixmobile.downloader.model.DownloadModel
|
||||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Successful
|
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Successful
|
||||||
import org.kiwix.kiwixmobile.downloader.model.DownloadStatus
|
import org.kiwix.kiwixmobile.downloader.model.DownloadStatus
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.UriToFileConverter
|
||||||
import org.kiwix.kiwixmobile.extensions.calculateSearchMatches
|
import org.kiwix.kiwixmobile.extensions.calculateSearchMatches
|
||||||
import org.kiwix.kiwixmobile.extensions.registerReceiver
|
import org.kiwix.kiwixmobile.extensions.registerReceiver
|
||||||
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity
|
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity
|
||||||
@ -71,7 +73,8 @@ class ZimManageViewModel @Inject constructor(
|
|||||||
private val context: Application,
|
private val context: Application,
|
||||||
private val connectivityBroadcastReceiver: ConnectivityBroadcastReceiver,
|
private val connectivityBroadcastReceiver: ConnectivityBroadcastReceiver,
|
||||||
private val bookUtils: BookUtils,
|
private val bookUtils: BookUtils,
|
||||||
private val fat32Checker: Fat32Checker
|
private val fat32Checker: Fat32Checker,
|
||||||
|
private val uriToFileConverter: UriToFileConverter
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val libraryItems: MutableLiveData<List<LibraryListItem>> = MutableLiveData()
|
val libraryItems: MutableLiveData<List<LibraryListItem>> = MutableLiveData()
|
||||||
@ -94,6 +97,11 @@ class ZimManageViewModel @Inject constructor(
|
|||||||
context.registerReceiver(connectivityBroadcastReceiver)
|
context.registerReceiver(connectivityBroadcastReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
fun onClearedExposed() {
|
||||||
|
onCleared()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
compositeDisposable.clear()
|
compositeDisposable.clear()
|
||||||
context.unregisterReceiver(connectivityBroadcastReceiver)
|
context.unregisterReceiver(connectivityBroadcastReceiver)
|
||||||
@ -155,6 +163,7 @@ class ZimManageViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
.buffer(3, SECONDS)
|
.buffer(3, SECONDS)
|
||||||
.map(this::downloadIdsWithNoStatusesOverBufferPeriod)
|
.map(this::downloadIdsWithNoStatusesOverBufferPeriod)
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
downloadDao.delete(*it.toLongArray())
|
downloadDao.delete(*it.toLongArray())
|
||||||
@ -411,7 +420,7 @@ class ZimManageViewModel @Inject constructor(
|
|||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
bookDao.insert(it.map { downloadStatus -> downloadStatus.toBookOnDisk() })
|
bookDao.insert(it.map { downloadStatus -> downloadStatus.toBookOnDisk(uriToFileConverter) })
|
||||||
downloadDao.delete(
|
downloadDao.delete(
|
||||||
*it.map { status -> status.downloadId }.toLongArray()
|
*it.map { status -> status.downloadId }.toLongArray()
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile
|
||||||
|
|
||||||
|
import android.arch.core.executor.ArchTaskExecutor
|
||||||
|
import android.arch.core.executor.TaskExecutor
|
||||||
|
import org.junit.jupiter.api.extension.AfterEachCallback
|
||||||
|
import org.junit.jupiter.api.extension.BeforeEachCallback
|
||||||
|
import org.junit.jupiter.api.extension.ExtensionContext
|
||||||
|
|
||||||
|
class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {
|
||||||
|
|
||||||
|
override fun beforeEach(context: ExtensionContext?) {
|
||||||
|
ArchTaskExecutor.getInstance()
|
||||||
|
.setDelegate(object : TaskExecutor() {
|
||||||
|
override fun executeOnDiskIO(runnable: Runnable) = runnable.run()
|
||||||
|
|
||||||
|
override fun postToMainThread(runnable: Runnable) = runnable.run()
|
||||||
|
|
||||||
|
override fun isMainThread(): Boolean = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterEach(context: ExtensionContext?) {
|
||||||
|
ArchTaskExecutor.getInstance().setDelegate(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (C) 2018 Kiwix <android.kiwix.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.zim_manager
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import com.jraska.livedata.test
|
||||||
|
import io.mockk.clearMocks
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import io.reactivex.Scheduler
|
||||||
|
import io.reactivex.android.plugins.RxAndroidPlugins
|
||||||
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
|
import io.reactivex.processors.PublishProcessor
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import io.reactivex.schedulers.TestScheduler
|
||||||
|
import org.junit.jupiter.api.AfterAll
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Nested
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
import org.kiwix.kiwixmobile.InstantExecutorExtension
|
||||||
|
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao
|
||||||
|
import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao
|
||||||
|
import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao
|
||||||
|
import org.kiwix.kiwixmobile.downloader.Downloader
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.BookOnDisk
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.DownloadItem
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.DownloadModel
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.DownloadState
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.DownloadStatus
|
||||||
|
import org.kiwix.kiwixmobile.downloader.model.UriToFileConverter
|
||||||
|
import org.kiwix.kiwixmobile.network.KiwixService
|
||||||
|
import org.kiwix.kiwixmobile.utils.BookUtils
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.Fat32Checker.FileSystemState
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.NetworkState.NOT_CONNECTED
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.StorageObserver
|
||||||
|
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.Language
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
|
|
||||||
|
@ExtendWith(InstantExecutorExtension::class)
|
||||||
|
class ZimManageViewModelTest {
|
||||||
|
|
||||||
|
private val newDownloadDao: NewDownloadDao = mockk()
|
||||||
|
private val newBookDao: NewBookDao = mockk()
|
||||||
|
private val newLanguagesDao: NewLanguagesDao = mockk()
|
||||||
|
private val downloader: Downloader = mockk()
|
||||||
|
private val storageObserver: StorageObserver = mockk()
|
||||||
|
private val kiwixService: KiwixService = mockk()
|
||||||
|
private val application: Application = mockk()
|
||||||
|
private val connectivityBroadcastReceiver: ConnectivityBroadcastReceiver = mockk()
|
||||||
|
private val bookUtils: BookUtils = mockk()
|
||||||
|
private val fat32Checker: Fat32Checker = mockk()
|
||||||
|
private val uriToFileConverter: UriToFileConverter = mockk()
|
||||||
|
lateinit var viewModel: ZimManageViewModel
|
||||||
|
|
||||||
|
private val downloads: PublishProcessor<List<DownloadModel>> = PublishProcessor.create()
|
||||||
|
private val books: PublishProcessor<List<BookOnDisk>> = PublishProcessor.create()
|
||||||
|
private val languages: PublishProcessor<List<Language>> = PublishProcessor.create()
|
||||||
|
private val fileSystemStates: PublishProcessor<FileSystemState> = PublishProcessor.create()
|
||||||
|
private val networkStates: PublishProcessor<NetworkState> = PublishProcessor.create()
|
||||||
|
|
||||||
|
private val testScheduler = TestScheduler()
|
||||||
|
|
||||||
|
init {
|
||||||
|
setScheduler(testScheduler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setScheduler(replacementScheduler: Scheduler) {
|
||||||
|
RxJavaPlugins.setIoSchedulerHandler { scheduler -> replacementScheduler }
|
||||||
|
RxJavaPlugins.setComputationSchedulerHandler { scheduler -> replacementScheduler }
|
||||||
|
RxJavaPlugins.setNewThreadSchedulerHandler { scheduler -> replacementScheduler }
|
||||||
|
RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler -> Schedulers.trampoline() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
fun teardown() {
|
||||||
|
RxJavaPlugins.reset()
|
||||||
|
RxAndroidPlugins.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun init() {
|
||||||
|
clearMocks(
|
||||||
|
newDownloadDao, newBookDao, newLanguagesDao, downloader,
|
||||||
|
storageObserver, kiwixService, application, connectivityBroadcastReceiver, bookUtils,
|
||||||
|
fat32Checker, uriToFileConverter
|
||||||
|
)
|
||||||
|
every { connectivityBroadcastReceiver.action } returns "test"
|
||||||
|
every { newDownloadDao.downloads() } returns downloads
|
||||||
|
every { newBookDao.books() } returns books
|
||||||
|
every { newLanguagesDao.languages() } returns languages
|
||||||
|
every { fat32Checker.fileSystemStates } returns fileSystemStates
|
||||||
|
every { connectivityBroadcastReceiver.networkStates } returns networkStates
|
||||||
|
every { application.registerReceiver(any(), any()) } returns mockk()
|
||||||
|
viewModel = ZimManageViewModel(
|
||||||
|
newDownloadDao, newBookDao, newLanguagesDao, downloader,
|
||||||
|
storageObserver, kiwixService, application, connectivityBroadcastReceiver, bookUtils,
|
||||||
|
fat32Checker, uriToFileConverter
|
||||||
|
)
|
||||||
|
testScheduler.triggerActions()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class Context {
|
||||||
|
@Test
|
||||||
|
fun `registers broadcastReceiver in init`() {
|
||||||
|
verify {
|
||||||
|
application.registerReceiver(connectivityBroadcastReceiver, any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unregisters broadcastReceiver in onCleared`() {
|
||||||
|
every { application.unregisterReceiver(any()) } returns mockk()
|
||||||
|
viewModel.onClearedExposed()
|
||||||
|
verify {
|
||||||
|
application.unregisterReceiver(connectivityBroadcastReceiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class Downloads {
|
||||||
|
@Test
|
||||||
|
fun `on emission from database query and render downloads`() {
|
||||||
|
val expectedStatus = DownloadStatus()
|
||||||
|
expectStatus(expectedStatus)
|
||||||
|
viewModel.downloadItems
|
||||||
|
.test()
|
||||||
|
.assertValue(listOf(DownloadItem(expectedStatus)))
|
||||||
|
.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `on emission of successful status create a book and delete the download`() {
|
||||||
|
every { newBookDao.insert(any()) } returns Unit
|
||||||
|
every { newDownloadDao.delete(any()) } returns Unit
|
||||||
|
every { uriToFileConverter.convert(any()) } returns File("test")
|
||||||
|
val expectedStatus = DownloadStatus(
|
||||||
|
downloadId = 10L,
|
||||||
|
state = DownloadState.Successful
|
||||||
|
)
|
||||||
|
expectStatus(expectedStatus)
|
||||||
|
val element = expectedStatus.toBookOnDisk(uriToFileConverter)
|
||||||
|
verify {
|
||||||
|
newBookDao.insert(listOf(element))
|
||||||
|
newDownloadDao.delete(10L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expectStatus(expectedStatus: DownloadStatus) {
|
||||||
|
val downloadList = listOf(DownloadModel())
|
||||||
|
every { downloader.queryStatus(downloadList) } returns listOf(expectedStatus)
|
||||||
|
downloads.offer(downloadList)
|
||||||
|
testScheduler.triggerActions()
|
||||||
|
testScheduler.advanceTimeBy(1, SECONDS)
|
||||||
|
testScheduler.triggerActions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class Books {
|
||||||
|
@Test
|
||||||
|
fun `emissions from DB sorted by title and observed`() {
|
||||||
|
books.onNext(
|
||||||
|
listOf(
|
||||||
|
BookOnDisk().apply { book.title = "z" },
|
||||||
|
BookOnDisk().apply { book.title = "a" }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
testScheduler.triggerActions()
|
||||||
|
viewModel.bookItems.test()
|
||||||
|
.assertValue(
|
||||||
|
listOf(
|
||||||
|
BookOnDisk().apply { book.title = "a" },
|
||||||
|
BookOnDisk().apply { book.title = "z" }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `network states observed`() {
|
||||||
|
networkStates.offer(NOT_CONNECTED)
|
||||||
|
viewModel.networkStates.test()
|
||||||
|
.assertValue(NOT_CONNECTED)
|
||||||
|
.dispose()
|
||||||
|
}
|
||||||
|
}
|
1
app/src/test/resources/junit-platform.properties
Normal file
1
app/src/test/resources/junit-platform.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
junit.jupiter.testinstance.lifecycle.default = per_class
|
Loading…
x
Reference in New Issue
Block a user