Skip to content

Commit

Permalink
fix unit-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
softartdev committed Oct 20, 2024
1 parent e546ffc commit fda640b
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 118 deletions.
10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ targetSdk = "34"
minSdk = "21"
jdk = "17"
kotlin = "2.0.21"
agp = "8.7.0"
agp = "8.7.1"
gms = "4.4.2"
crashlytics = "3.0.2"
compose = "1.6.11"
Expand All @@ -18,17 +18,17 @@ koin = "3.5.6"
kotlinx-datetime = "0.6.0"
napier = "2.7.1"
materialThemePrefs = "0.9.0"
androidxViewModel = "2.8.2"
androidxViewModel = "2.8.3"
androidxNavigation = "2.7.0-alpha07"
androidxActivityCompose = "1.9.2"
androidxComposeTest = "1.7.3"
androidxActivityCompose = "1.9.3"
androidxComposeTest = "1.7.4"
androidxCoreSplashscreen = "1.0.1"
androidxTracing = "1.2.0"
androidxLifecycle = "2.8.6"
androidxArch = "2.2.0"
androidxTestExt = "1.2.1"
androidxTest = "1.6.2"
androidxTestOrchestrator = "1.5.0"
androidxTestOrchestrator = "1.5.1"
firebase = "33.4.0"
leakCanary = "2.14"
junit = "4.13.2"
Expand Down
190 changes: 93 additions & 97 deletions iosApp/Pods/Pods.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.softartdev.notedelight.shared.presentation.note
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import app.cash.turbine.test
import com.softartdev.notedelight.shared.CoroutineDispatchersStub
import com.softartdev.notedelight.shared.PrintAntilog
import com.softartdev.notedelight.shared.date.createLocalDateTime
import com.softartdev.notedelight.shared.db.Note
import com.softartdev.notedelight.shared.db.NoteDAO
Expand All @@ -15,6 +16,7 @@ import com.softartdev.notedelight.shared.usecase.note.CreateNoteUseCase
import com.softartdev.notedelight.shared.usecase.note.DeleteNoteUseCase
import com.softartdev.notedelight.shared.usecase.note.SaveNoteUseCase
import com.softartdev.notedelight.shared.usecase.note.UpdateTitleUseCase
import io.github.aakira.napier.Napier
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.LocalDateTime
Expand All @@ -35,11 +37,11 @@ class NoteViewModelTest {

private val mockNoteDAO = Mockito.mock(NoteDAO::class.java)
private val mockCreateNoteUseCase = Mockito.mock(CreateNoteUseCase::class.java)
private val mockSaveNoteUseCase = Mockito.mock(SaveNoteUseCase::class.java)
private val saveNoteUseCase = SaveNoteUseCase(mockNoteDAO)
private val mockDeleteNoteUseCase = Mockito.mock(DeleteNoteUseCase::class.java)
private val mockRouter = Mockito.mock(Router::class.java)
private val coroutineDispatchers = CoroutineDispatchersStub(testDispatcher = mainDispatcherRule.testDispatcher)
private val noteViewModel = NoteViewModel(mockNoteDAO, mockCreateNoteUseCase, mockSaveNoteUseCase, mockDeleteNoteUseCase, mockRouter, coroutineDispatchers)
private val noteViewModel = NoteViewModel(mockNoteDAO, mockCreateNoteUseCase, saveNoteUseCase, mockDeleteNoteUseCase, mockRouter, coroutineDispatchers)

private val id = 1L
private val title: String = "title"
Expand All @@ -49,13 +51,15 @@ class NoteViewModelTest {

@Before
fun setUp() = runTest {
Napier.base(PrintAntilog())
Mockito.`when`(mockCreateNoteUseCase.invoke()).thenReturn(id)
Mockito.`when`(mockNoteDAO.load(id)).thenReturn(note)
}

@After
fun tearDown() = runTest {
noteViewModel.onCleared()
Napier.takeLogarithm()
}

@Test
Expand Down Expand Up @@ -146,6 +150,10 @@ class NoteViewModelTest {
noteViewModel.checkSaveChange(title, text)
Mockito.verify(mockRouter).navigate(route = AppNavGraph.SaveChangesDialog.name)

SaveNoteUseCase.dialogChannel.send(true)
Mockito.verify(mockRouter).popBackStack()

Mockito.verifyNoMoreInteractions(mockRouter)
cancelAndIgnoreRemainingEvents()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,71 @@
package com.softartdev.notedelight.shared.presentation.note

import com.softartdev.notedelight.shared.CoroutineDispatchersStub
import com.softartdev.notedelight.shared.PrintAntilog
import com.softartdev.notedelight.shared.db.NoteDAO
import com.softartdev.notedelight.shared.navigation.Router
import com.softartdev.notedelight.shared.presentation.MainDispatcherRule
import com.softartdev.notedelight.shared.usecase.note.SaveNoteUseCase
import io.github.aakira.napier.Napier
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.seconds

class SaveViewModelTest {

@get:Rule
val mainDispatcherRule = MainDispatcherRule()

private val mockRouter = Mockito.mock(Router::class.java)
private val mockNoteDAO = Mockito.mock(NoteDAO::class.java)
private lateinit var saveNoteUseCase: SaveNoteUseCase
private val coroutineDispatchers = CoroutineDispatchersStub(
scheduler = mainDispatcherRule.testDispatcher.scheduler
)
private val saveViewModel: SaveViewModel = SaveViewModel(mockRouter, coroutineDispatchers)
private lateinit var saveViewModel: SaveViewModel

@Before
fun setUp() = runTest(context = coroutineDispatchers.default) {
Napier.base(PrintAntilog())
saveNoteUseCase = SaveNoteUseCase(mockNoteDAO)
saveViewModel = SaveViewModel(mockRouter, coroutineDispatchers)
}

@After
fun tearDown() = Napier.takeLogarithm()

@Test
fun `Don't save and nav back`() = runTest {
saveViewModel.doNotSaveAndNavBack()
advanceUntilIdle()
assertFalse(SaveNoteUseCase.saveChannel.receiveCatching().getOrThrow())
fun `save and nav back`() = runTest(timeout = 3.seconds) {
val deferred: Deferred<Boolean> = async { SaveNoteUseCase.dialogChannel.receive() }
saveViewModel.saveNoteAndNavBack()
advanceUntilIdle()
Mockito.verify(mockRouter).popBackStack()
assertTrue(deferred.await())
Mockito.verifyNoMoreInteractions(mockRouter)
}

@Test
fun `save and nav back`() = runTest {
saveViewModel.saveNoteAndNavBack()
advanceUntilIdle()
assertTrue(SaveNoteUseCase.saveChannel.receiveCatching().getOrThrow())
fun `don't save and nav back`() = runTest(timeout = 3.seconds) {
val deferred: Deferred<Boolean> = async { SaveNoteUseCase.dialogChannel.receive() }
saveViewModel.doNotSaveAndNavBack()
advanceUntilIdle()
Mockito.verify(mockRouter).popBackStack()
assertFalse(deferred.await())
Mockito.verifyNoMoreInteractions(mockRouter)
}

@Test
fun `navigate up`() = runTest {
fun `navigate up`() = runTest(timeout = 3.seconds) {
saveViewModel.navigateUp()
advanceUntilIdle()
Mockito.verify(mockRouter).popBackStack()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ class NoteViewModel(
}

private fun subscribeToSaveNote(title: String?, text: String) = viewModelScope.launch {
Napier.d("Subscribe to save note dialog channel")
val doSave: Boolean = withContext(coroutineDispatchers.io) {
SaveNoteUseCase.saveChannel.receive()
SaveNoteUseCase.dialogChannel.receive()
}
when {
doSave -> saveNoteAndNavBack(title, text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ class SaveViewModel(
) : ViewModel() {

fun saveNoteAndNavBack() = viewModelScope.launch(context = coroutineDispatchers.default) {
SaveNoteUseCase.saveChannel.send(true)
SaveNoteUseCase.dialogChannel.send(true)
navigateUp()
}

fun doNotSaveAndNavBack() = viewModelScope.launch(context = coroutineDispatchers.default) {
SaveNoteUseCase.saveChannel.send(false)
SaveNoteUseCase.dialogChannel.send(false)
navigateUp()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ class SaveNoteUseCase(private val noteDAO: NoteDAO) : (Long, String, String) ->
}

companion object {
val saveChannel: Channel<Boolean> by lazy { return@lazy Channel<Boolean>() }
val dialogChannel: Channel<Boolean> by lazy { return@lazy Channel<Boolean>() }
}
}

0 comments on commit fda640b

Please sign in to comment.