Issue#11 Adjust TestMainDispatcher extension using tests after coroutine update

This commit is contained in:
Gergely Hegedus 2022-01-23 21:07:46 +02:00
parent 3c85431d96
commit 46d9263742
5 changed files with 70 additions and 68 deletions

View file

@ -1,7 +1,10 @@
package org.fnives.test.showcase.testutils package org.fnives.test.showcase.testutils
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.TestCoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain import kotlinx.coroutines.test.setMain
import org.fnives.test.showcase.storage.database.DatabaseInitialization import org.fnives.test.showcase.storage.database.DatabaseInitialization
@ -15,12 +18,12 @@ import org.junit.jupiter.api.extension.ExtensionContext
* *
* One can access the test dispatcher via [testDispatcher] static getter. * One can access the test dispatcher via [testDispatcher] static getter.
*/ */
@OptIn(ExperimentalCoroutinesApi::class)
class TestMainDispatcher : BeforeEachCallback, AfterEachCallback { class TestMainDispatcher : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) { override fun beforeEach(context: ExtensionContext?) {
val testDispatcher = TestCoroutineDispatcher() val testDispatcher = StandardTestDispatcher(TestCoroutineScheduler())
privateTestDispatcher = testDispatcher privateTestDispatcher = testDispatcher
testDispatcher.pauseDispatcher()
DatabaseInitialization.dispatcher = testDispatcher DatabaseInitialization.dispatcher = testDispatcher
Dispatchers.setMain(testDispatcher) Dispatchers.setMain(testDispatcher)
} }
@ -31,8 +34,9 @@ class TestMainDispatcher : BeforeEachCallback, AfterEachCallback {
} }
companion object { companion object {
private var privateTestDispatcher: TestCoroutineDispatcher? = null private var privateTestDispatcher: TestDispatcher? = null
val testDispatcher: TestCoroutineDispatcher val testDispatcher: TestDispatcher
get() = privateTestDispatcher ?: throw IllegalStateException("TestMainDispatcher is in afterEach State") get() = privateTestDispatcher
?: throw IllegalStateException("TestMainDispatcher is in afterEach State")
} }
} }

View file

@ -1,6 +1,7 @@
package org.fnives.test.showcase.ui.auth package org.fnives.test.showcase.ui.auth
import com.jraska.livedata.test import com.jraska.livedata.test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.fnives.test.showcase.core.login.LoginUseCase import org.fnives.test.showcase.core.login.LoginUseCase
import org.fnives.test.showcase.model.auth.LoginCredentials import org.fnives.test.showcase.model.auth.LoginCredentials
@ -27,11 +28,12 @@ import java.util.stream.Stream
@Suppress("TestFunctionName") @Suppress("TestFunctionName")
@ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class) @ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class)
@OptIn(ExperimentalCoroutinesApi::class)
internal class AuthViewModelTest { internal class AuthViewModelTest {
private lateinit var sut: AuthViewModel private lateinit var sut: AuthViewModel
private lateinit var mockLoginUseCase: LoginUseCase private lateinit var mockLoginUseCase: LoginUseCase
private val testDispatcher get() = TestMainDispatcher.testDispatcher private val testScheduler get() = TestMainDispatcher.testDispatcher.scheduler
@BeforeEach @BeforeEach
fun setUp() { fun setUp() {
@ -42,7 +44,7 @@ internal class AuthViewModelTest {
@DisplayName("GIVEN initialized viewModel WHEN observed THEN loading false other fields are empty") @DisplayName("GIVEN initialized viewModel WHEN observed THEN loading false other fields are empty")
@Test @Test
fun initialSetup() { fun initialSetup() {
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
sut.username.test().assertNoValue() sut.username.test().assertNoValue()
sut.password.test().assertNoValue() sut.password.test().assertNoValue()
@ -54,11 +56,11 @@ internal class AuthViewModelTest {
@DisplayName("GIVEN password text WHEN onPasswordChanged is called THEN password livedata is updated") @DisplayName("GIVEN password text WHEN onPasswordChanged is called THEN password livedata is updated")
@Test @Test
fun whenPasswordChangedLiveDataIsUpdated() { fun whenPasswordChangedLiveDataIsUpdated() {
testDispatcher.resumeDispatcher()
val passwordTestObserver = sut.password.test() val passwordTestObserver = sut.password.test()
sut.onPasswordChanged("a") sut.onPasswordChanged("a")
sut.onPasswordChanged("al") sut.onPasswordChanged("al")
testScheduler.advanceUntilIdle()
passwordTestObserver.assertValueHistory("a", "al") passwordTestObserver.assertValueHistory("a", "al")
sut.username.test().assertNoValue() sut.username.test().assertNoValue()
@ -70,11 +72,11 @@ internal class AuthViewModelTest {
@DisplayName("GIVEN username text WHEN onUsernameChanged is called THEN username livedata is updated") @DisplayName("GIVEN username text WHEN onUsernameChanged is called THEN username livedata is updated")
@Test @Test
fun whenUsernameChangedLiveDataIsUpdated() { fun whenUsernameChangedLiveDataIsUpdated() {
testDispatcher.resumeDispatcher()
val usernameTestObserver = sut.username.test() val usernameTestObserver = sut.username.test()
sut.onUsernameChanged("a") sut.onUsernameChanged("a")
sut.onUsernameChanged("al") sut.onUsernameChanged("al")
testScheduler.advanceUntilIdle()
usernameTestObserver.assertValueHistory("a", "al") usernameTestObserver.assertValueHistory("a", "al")
sut.password.test().assertNoValue() sut.password.test().assertNoValue()
@ -92,7 +94,7 @@ internal class AuthViewModelTest {
} }
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
loadingTestObserver.assertValueHistory(false, true, false) loadingTestObserver.assertValueHistory(false, true, false)
runBlocking { verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("", "")) } runBlocking { verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("", "")) }
@ -106,7 +108,7 @@ internal class AuthViewModelTest {
sut.onLogin() sut.onLogin()
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
runBlocking { verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("", "")) } runBlocking { verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("", "")) }
verifyNoMoreInteractions(mockLoginUseCase) verifyNoMoreInteractions(mockLoginUseCase)
@ -122,7 +124,7 @@ internal class AuthViewModelTest {
sut.onUsernameChanged("usr") sut.onUsernameChanged("usr")
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
runBlocking { runBlocking {
verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("usr", "pass")) verify(mockLoginUseCase, times(1)).invoke(LoginCredentials("usr", "pass"))
@ -141,7 +143,7 @@ internal class AuthViewModelTest {
val navigateToHomeObserver = sut.navigateToHome.test() val navigateToHomeObserver = sut.navigateToHome.test()
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
loadingObserver.assertValueHistory(false, true, false) loadingObserver.assertValueHistory(false, true, false)
errorObserver.assertValueHistory(Event(AuthViewModel.ErrorType.GENERAL_NETWORK_ERROR)) errorObserver.assertValueHistory(Event(AuthViewModel.ErrorType.GENERAL_NETWORK_ERROR))
@ -162,7 +164,7 @@ internal class AuthViewModelTest {
val navigateToHomeObserver = sut.navigateToHome.test() val navigateToHomeObserver = sut.navigateToHome.test()
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
loadingObserver.assertValueHistory(false, true, false) loadingObserver.assertValueHistory(false, true, false)
errorObserver.assertValueHistory(Event(errorType)) errorObserver.assertValueHistory(Event(errorType))
@ -180,7 +182,7 @@ internal class AuthViewModelTest {
val navigateToHomeObserver = sut.navigateToHome.test() val navigateToHomeObserver = sut.navigateToHome.test()
sut.onLogin() sut.onLogin()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
loadingObserver.assertValueHistory(false, true, false) loadingObserver.assertValueHistory(false, true, false)
errorObserver.assertNoValue() errorObserver.assertNoValue()

View file

@ -1,6 +1,7 @@
package org.fnives.test.showcase.ui.home package org.fnives.test.showcase.ui.home
import com.jraska.livedata.test import com.jraska.livedata.test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
@ -29,6 +30,7 @@ import org.mockito.kotlin.whenever
@Suppress("TestFunctionName") @Suppress("TestFunctionName")
@ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class) @ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class)
@OptIn(ExperimentalCoroutinesApi::class)
internal class MainViewModelTest { internal class MainViewModelTest {
private lateinit var sut: MainViewModel private lateinit var sut: MainViewModel
@ -37,7 +39,7 @@ internal class MainViewModelTest {
private lateinit var mockFetchContentUseCase: FetchContentUseCase private lateinit var mockFetchContentUseCase: FetchContentUseCase
private lateinit var mockAddContentToFavouriteUseCase: AddContentToFavouriteUseCase private lateinit var mockAddContentToFavouriteUseCase: AddContentToFavouriteUseCase
private lateinit var mockRemoveContentFromFavouritesUseCase: RemoveContentFromFavouritesUseCase private lateinit var mockRemoveContentFromFavouritesUseCase: RemoveContentFromFavouritesUseCase
private val testDispatcher get() = TestMainDispatcher.testDispatcher private val testScheduler get() = TestMainDispatcher.testDispatcher.scheduler
@BeforeEach @BeforeEach
fun setUp() { fun setUp() {
@ -46,7 +48,6 @@ internal class MainViewModelTest {
mockFetchContentUseCase = mock() mockFetchContentUseCase = mock()
mockAddContentToFavouriteUseCase = mock() mockAddContentToFavouriteUseCase = mock()
mockRemoveContentFromFavouritesUseCase = mock() mockRemoveContentFromFavouritesUseCase = mock()
testDispatcher.pauseDispatcher()
sut = MainViewModel( sut = MainViewModel(
getAllContentUseCase = mockGetAllContentUseCase, getAllContentUseCase = mockGetAllContentUseCase,
logoutUseCase = mockLogoutUseCase, logoutUseCase = mockLogoutUseCase,
@ -69,13 +70,16 @@ internal class MainViewModelTest {
@Test @Test
fun loadingDataShowsInLoadingUIState() { fun loadingDataShowsInLoadingUIState() {
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading())) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading()))
testDispatcher.resumeDispatcher() val errorMessageTestObserver = sut.errorMessage.test()
testDispatcher.advanceUntilIdle() val contentTestObserver = sut.content.test()
val loadingTestObserver = sut.loading.test()
val navigateToAuthTestObserver = sut.navigateToAuth.test()
testScheduler.advanceUntilIdle()
sut.errorMessage.test().assertValue(false) errorMessageTestObserver.assertValue(false)
sut.content.test().assertNoValue() contentTestObserver.assertNoValue()
sut.loading.test().assertValue(true) loadingTestObserver.assertValue(true)
sut.navigateToAuth.test().assertNoValue() navigateToAuthTestObserver.assertNoValue()
} }
@DisplayName("GIVEN loading then data WHEN observing content THEN proper states are shown") @DisplayName("GIVEN loading then data WHEN observing content THEN proper states are shown")
@ -85,13 +89,13 @@ internal class MainViewModelTest {
val errorMessageTestObserver = sut.errorMessage.test() val errorMessageTestObserver = sut.errorMessage.test()
val contentTestObserver = sut.content.test() val contentTestObserver = sut.content.test()
val loadingTestObserver = sut.loading.test() val loadingTestObserver = sut.loading.test()
testDispatcher.resumeDispatcher() val navigateToAuthTestObserver = sut.navigateToAuth.test()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
errorMessageTestObserver.assertValueHistory(false) errorMessageTestObserver.assertValueHistory(false)
contentTestObserver.assertValueHistory(listOf()) contentTestObserver.assertValueHistory(listOf())
loadingTestObserver.assertValueHistory(true, false) loadingTestObserver.assertValueHistory(true, false)
sut.navigateToAuth.test().assertNoValue() navigateToAuthTestObserver.assertNoValue()
} }
@DisplayName("GIVEN loading then error WHEN observing content THEN proper states are shown") @DisplayName("GIVEN loading then error WHEN observing content THEN proper states are shown")
@ -101,13 +105,13 @@ internal class MainViewModelTest {
val errorMessageTestObserver = sut.errorMessage.test() val errorMessageTestObserver = sut.errorMessage.test()
val contentTestObserver = sut.content.test() val contentTestObserver = sut.content.test()
val loadingTestObserver = sut.loading.test() val loadingTestObserver = sut.loading.test()
testDispatcher.resumeDispatcher() val navigateToAuthTestObserver = sut.navigateToAuth.test()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
errorMessageTestObserver.assertValueHistory(false, true) errorMessageTestObserver.assertValueHistory(false, true)
contentTestObserver.assertValueHistory(emptyList()) contentTestObserver.assertValueHistory(emptyList())
loadingTestObserver.assertValueHistory(true, false) loadingTestObserver.assertValueHistory(true, false)
sut.navigateToAuth.test().assertNoValue() navigateToAuthTestObserver.assertNoValue()
} }
@DisplayName("GIVEN loading then error then loading then data WHEN observing content THEN proper states are shown") @DisplayName("GIVEN loading then error then loading then data WHEN observing content THEN proper states are shown")
@ -127,13 +131,13 @@ internal class MainViewModelTest {
val errorMessageTestObserver = sut.errorMessage.test() val errorMessageTestObserver = sut.errorMessage.test()
val contentTestObserver = sut.content.test() val contentTestObserver = sut.content.test()
val loadingTestObserver = sut.loading.test() val loadingTestObserver = sut.loading.test()
testDispatcher.resumeDispatcher() val navigateToAuthTestObserver = sut.navigateToAuth.test()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
errorMessageTestObserver.assertValueHistory(false, true, false) errorMessageTestObserver.assertValueHistory(false, true, false)
contentTestObserver.assertValueHistory(emptyList(), content) contentTestObserver.assertValueHistory(emptyList(), content)
loadingTestObserver.assertValueHistory(true, false, true, false) loadingTestObserver.assertValueHistory(true, false, true, false)
sut.navigateToAuth.test().assertNoValue() navigateToAuthTestObserver.assertNoValue()
} }
@DisplayName("GIVEN loading viewModel WHEN refreshing THEN usecase is not called") @DisplayName("GIVEN loading viewModel WHEN refreshing THEN usecase is not called")
@ -141,11 +145,10 @@ internal class MainViewModelTest {
fun fetchIsIgnoredIfViewModelIsStillLoading() { fun fetchIsIgnoredIfViewModelIsStillLoading() {
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading())) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading()))
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onRefresh() sut.onRefresh()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
verifyZeroInteractions(mockFetchContentUseCase) verifyZeroInteractions(mockFetchContentUseCase)
} }
@ -155,11 +158,10 @@ internal class MainViewModelTest {
fun fetchIsCalledIfViewModelIsLoaded() { fun fetchIsCalledIfViewModelIsLoaded() {
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf()) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf())
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onRefresh() sut.onRefresh()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
verify(mockFetchContentUseCase, times(1)).invoke() verify(mockFetchContentUseCase, times(1)).invoke()
verifyNoMoreInteractions(mockFetchContentUseCase) verifyNoMoreInteractions(mockFetchContentUseCase)
@ -170,11 +172,10 @@ internal class MainViewModelTest {
fun loadingViewModelStillCalsLogout() { fun loadingViewModelStillCalsLogout() {
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading())) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Loading()))
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onLogout() sut.onLogout()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
runBlocking { verify(mockLogoutUseCase, times(1)).invoke() } runBlocking { verify(mockLogoutUseCase, times(1)).invoke() }
verifyNoMoreInteractions(mockLogoutUseCase) verifyNoMoreInteractions(mockLogoutUseCase)
@ -185,11 +186,10 @@ internal class MainViewModelTest {
fun nonLoadingViewModelStillCalsLogout() { fun nonLoadingViewModelStillCalsLogout() {
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf()) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf())
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onLogout() sut.onLogout()
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
runBlocking { verify(mockLogoutUseCase, times(1)).invoke() } runBlocking { verify(mockLogoutUseCase, times(1)).invoke() }
verifyNoMoreInteractions(mockLogoutUseCase) verifyNoMoreInteractions(mockLogoutUseCase)
@ -204,11 +204,10 @@ internal class MainViewModelTest {
) )
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents))) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents)))
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onFavouriteToggleClicked(ContentId("c")) sut.onFavouriteToggleClicked(ContentId("c"))
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
verifyZeroInteractions(mockRemoveContentFromFavouritesUseCase) verifyZeroInteractions(mockRemoveContentFromFavouritesUseCase)
verifyZeroInteractions(mockAddContentToFavouriteUseCase) verifyZeroInteractions(mockAddContentToFavouriteUseCase)
@ -223,11 +222,10 @@ internal class MainViewModelTest {
) )
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents))) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents)))
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onFavouriteToggleClicked(ContentId("b")) sut.onFavouriteToggleClicked(ContentId("b"))
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
runBlocking { verify(mockRemoveContentFromFavouritesUseCase, times(1)).invoke(ContentId("b")) } runBlocking { verify(mockRemoveContentFromFavouritesUseCase, times(1)).invoke(ContentId("b")) }
verifyNoMoreInteractions(mockRemoveContentFromFavouritesUseCase) verifyNoMoreInteractions(mockRemoveContentFromFavouritesUseCase)
@ -243,11 +241,10 @@ internal class MainViewModelTest {
) )
whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents))) whenever(mockGetAllContentUseCase.get()).doReturn(flowOf(Resource.Success(contents)))
sut.content.test() sut.content.test()
testDispatcher.resumeDispatcher() testScheduler.advanceUntilIdle()
testDispatcher.advanceUntilIdle()
sut.onFavouriteToggleClicked(ContentId("a")) sut.onFavouriteToggleClicked(ContentId("a"))
testDispatcher.advanceUntilIdle() testScheduler.advanceUntilIdle()
verifyZeroInteractions(mockRemoveContentFromFavouritesUseCase) verifyZeroInteractions(mockRemoveContentFromFavouritesUseCase)
runBlocking { verify(mockAddContentToFavouriteUseCase, times(1)).invoke(ContentId("a")) } runBlocking { verify(mockAddContentToFavouriteUseCase, times(1)).invoke(ContentId("a")) }

View file

@ -1,6 +1,7 @@
package org.fnives.test.showcase.ui.splash package org.fnives.test.showcase.ui.splash
import com.jraska.livedata.test import com.jraska.livedata.test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase
import org.fnives.test.showcase.testutils.InstantExecutorExtension import org.fnives.test.showcase.testutils.InstantExecutorExtension
import org.fnives.test.showcase.testutils.TestMainDispatcher import org.fnives.test.showcase.testutils.TestMainDispatcher
@ -14,11 +15,12 @@ import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever import org.mockito.kotlin.whenever
@ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class) @ExtendWith(InstantExecutorExtension::class, TestMainDispatcher::class)
@OptIn(ExperimentalCoroutinesApi::class)
internal class SplashViewModelTest { internal class SplashViewModelTest {
private lateinit var mockIsUserLoggedInUseCase: IsUserLoggedInUseCase private lateinit var mockIsUserLoggedInUseCase: IsUserLoggedInUseCase
private lateinit var sut: SplashViewModel private lateinit var sut: SplashViewModel
private val testCoroutineDispatcher get() = TestMainDispatcher.testDispatcher private val testScheduler get() = TestMainDispatcher.testDispatcher.scheduler
@BeforeEach @BeforeEach
fun setUp() { fun setUp() {
@ -30,29 +32,32 @@ internal class SplashViewModelTest {
@Test @Test
fun loggedOutUserGoesToAuthentication() { fun loggedOutUserGoesToAuthentication() {
whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(false) whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(false)
val navigateToTestObserver = sut.navigateTo.test()
testCoroutineDispatcher.advanceTimeBy(500) testScheduler.advanceTimeBy(501)
sut.navigateTo.test().assertValue(Event(SplashViewModel.NavigateTo.AUTHENTICATION)) navigateToTestObserver.assertValueHistory(Event(SplashViewModel.NavigateTo.AUTHENTICATION))
} }
@DisplayName("GIVEN logged in user WHEN splash started THEN after half a second navigated to home") @DisplayName("GIVEN logged in user WHEN splash started THEN after half a second navigated to home")
@Test @Test
fun loggedInUserGoestoHome() { fun loggedInUserGoesToHome() {
whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(true) whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(true)
val navigateToTestObserver = sut.navigateTo.test()
testCoroutineDispatcher.advanceTimeBy(500) testScheduler.advanceTimeBy(501)
sut.navigateTo.test().assertValue(Event(SplashViewModel.NavigateTo.HOME)) navigateToTestObserver.assertValueHistory(Event(SplashViewModel.NavigateTo.HOME))
} }
@DisplayName("GIVEN not logged in user WHEN splash started THEN before half a second no event is sent") @DisplayName("GIVEN not logged in user WHEN splash started THEN before half a second no event is sent")
@Test @Test
fun withoutEnoughTimeNoNavigationHappens() { fun withoutEnoughTimeNoNavigationHappens() {
whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(false) whenever(mockIsUserLoggedInUseCase.invoke()).doReturn(false)
val navigateToTestObserver = sut.navigateTo.test()
testCoroutineDispatcher.advanceTimeBy(100) testScheduler.advanceTimeBy(500)
sut.navigateTo.test().assertNoValue() navigateToTestObserver.assertNoValue()
} }
} }

View file

@ -7,7 +7,6 @@ import org.fnives.test.showcase.ui.auth.AuthViewModel
import org.fnives.test.showcase.ui.home.MainViewModel import org.fnives.test.showcase.ui.home.MainViewModel
import org.fnives.test.showcase.ui.splash.SplashViewModel import org.fnives.test.showcase.ui.splash.SplashViewModel
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.extension.ExtendWith
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
@ -28,11 +27,6 @@ class DITest : KoinTest {
private val mainViewModel by inject<MainViewModel>() private val mainViewModel by inject<MainViewModel>()
private val splashViewModel by inject<SplashViewModel>() private val splashViewModel by inject<SplashViewModel>()
@BeforeEach
fun setUp() {
TestMainDispatcher.testDispatcher.pauseDispatcher()
}
@AfterEach @AfterEach
fun tearDown() { fun tearDown() {
stopKoin() stopKoin()