Skip to content

Commit

Permalink
Fixed the FavoriteArticlesViewModeltest
Browse files Browse the repository at this point in the history
  • Loading branch information
nsmirosh committed Dec 22, 2024
1 parent 92813f0 commit 293f9bf
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 178 deletions.
17 changes: 5 additions & 12 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ plugins {
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
id("org.jetbrains.kotlin.plugin.compose")
// kotlin("kapt")
// kotlin("ksp")
kotlin("plugin.serialization") version "2.0.21"
}

Expand Down Expand Up @@ -111,14 +109,13 @@ dependencies {
implementation("androidx.room:room-ktx:$room")


// To use Kotlin annotation processing tool (kapt)
// kapt("androidx.room:room-compiler:$room")
ksp("androidx.room:room-compiler:$room")
val bom = "2024.12.01"

val composeBom = "2024.12.01"

implementation("androidx.core:core-ktx:1.15.0")
implementation("androidx.activity:activity-compose:1.9.3")
implementation(platform("androidx.compose:compose-bom:$bom"))
implementation(platform("androidx.compose:compose-bom:$composeBom"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
Expand All @@ -142,12 +139,8 @@ dependencies {

androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation(platform("androidx.compose:compose-bom:$bom"))
androidTestImplementation(platform("androidx.compose:compose-bom:$composeBom"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.7.6")
debugImplementation("androidx.compose.ui:ui-test-manifest:1.7.6")
}

//kapt {
// correctErrorTypes = true
//}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import nick.mirosh.newsapp.HiltTestActivity
import nick.mirosh.newsapp.di.NetworkResponseBehavior
import nick.mirosh.newsapp.ui.theme.NewsAppTheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface ArticleDao {
fun getAllArticles(): List<DatabaseArticle>

@Query("SELECT * FROM articles WHERE liked = 1")
fun getLikedArticles(): Flow<List<DatabaseArticle>>
fun getLikedArticles(): Flow<List<DatabaseArticle>?>

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertAll(articles: List<DatabaseArticle>): List<Long>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,14 @@ class NewsRepositoryImpl(
}


override suspend fun getFavoriteArticles() = flow {
try {
newsLocalDataSource.getLikedArticles().collect {
emit(Result.Success(databaseToDomainArticleMapper.map(it)))
override fun getFavoriteArticles() =
newsLocalDataSource.getLikedArticles().map { articles ->
if (articles != null) {
Result.Success(databaseToDomainArticleMapper.map(articles))
} else {
Result.Error(ErrorType.General)
}
} catch (e: Exception) {
Log.e(TAG, e.message.toString())
emit(Result.Error(ErrorType.General))
}
}

override suspend fun updateArticle(article: Article) =
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import nick.mirosh.newsapp.domain.feed.model.Article

interface NewsRepository {
suspend fun getNewsArticles(country: String): Result<List<Article>>
suspend fun getFavoriteArticles(): Flow<Result<List<Article>>>
fun getFavoriteArticles(): Flow<Result<List<Article>>>
suspend fun updateArticle(article: Article): Result<Article>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@ import nick.mirosh.newsapp.domain.feed.repository.NewsRepository
class FetchFavoriteArticlesUsecase (
private val repository: NewsRepository,
) {

suspend operator fun invoke(): Flow<Result<List<Article>>> = repository.getFavoriteArticles()

operator fun invoke(): Flow<Result<List<Article>>> = repository.getFavoriteArticles()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,32 @@ package nick.mirosh.newsapp.ui.favorite_articles

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import nick.mirosh.newsapp.domain.Result
import nick.mirosh.newsapp.domain.usecase.articles.FetchFavoriteArticlesUsecase
import nick.mirosh.newsapp.utils.MyLogger

class FavoriteArticlesViewModel (
class FavoriteArticlesViewModel(
private val fetchFavoriteArticlesUsecase: FetchFavoriteArticlesUsecase
) : ViewModel() {

private val _uiState = MutableStateFlow<FavoriteArticlesUIState>(FavoriteArticlesUIState.Loading)
val uiState = _uiState.asStateFlow()
val uiState = fetchFavoriteArticlesUsecase().map { result ->
when (result) {
is Result.Success ->
if (result.data.isEmpty())
FavoriteArticlesUIState.FavoriteArticlesEmpty
else
FavoriteArticlesUIState.FavoriteArticles(result.data)

init {
viewModelScope.launch {
fetchFavoriteArticlesUsecase().collect { result ->
when(result) {
is Result.Success ->
_uiState.value = if (result.data.isEmpty())
FavoriteArticlesUIState.FavoriteArticlesEmpty
else
FavoriteArticlesUIState.FavoriteArticles(result.data)

is Result.Error -> {
_uiState.value = FavoriteArticlesUIState.Failed
MyLogger.e("FavoriteArticlesViewModel", "Error = ${result.error}")
}
}

}
is Result.Error ->
FavoriteArticlesUIState.Failed
}
}
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
FavoriteArticlesUIState.Loading
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package nick.mirosh.newsapp

import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import nick.mirosh.newsapp.domain.Result
import nick.mirosh.newsapp.domain.feed.model.Article
Expand All @@ -21,18 +25,28 @@ class FavoriteArticlesViewModelTest {
@get:Rule
val mainDispatcherRule = MainDispatcherRule()

private var fetchFavoriteArticlesUsecase: FetchFavoriteArticlesUsecase = mockk<FetchFavoriteArticlesUsecase>()
private var fetchFavoriteArticlesUsecase: FetchFavoriteArticlesUsecase =
mockk<FetchFavoriteArticlesUsecase>()

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun init_withEmptyArticleResponse_sends_FavoriteArticlesEmptyEvent_toTheUI() = runTest {
fun init_withEmptyArticleResponse_sends_FavoriteArticlesEmptyEvent_toTheUI() = runTest(
StandardTestDispatcher()
) {

//Arrange
val result = Result.Success(listOf<Article>())
coEvery { fetchFavoriteArticlesUsecase.invoke() } returns flowOf(result)
coEvery { fetchFavoriteArticlesUsecase.invoke() } returns flowOf(Result.Success(listOf()))

//Act
val viewModel = FavoriteArticlesViewModel(fetchFavoriteArticlesUsecase)
val emissions = viewModel.uiState.take(2).toList()

val emissions = mutableListOf<FavoriteArticlesUIState>()
val job = launch {
viewModel.uiState.take(2).toList(emissions)
}
advanceUntilIdle()

job.cancel()

//Assert
assertEquals(FavoriteArticlesUIState.Loading, emissions[0])
Expand Down
Loading

0 comments on commit 293f9bf

Please sign in to comment.