Skip to content

Commit

Permalink
Merge pull request #37 from azrael8576/test/unit-test
Browse files Browse the repository at this point in the history
Add Unit tests PixabayImagePagingSourceTest
  • Loading branch information
azrael8576 authored Dec 19, 2023
2 parents 6a19543 + b07665c commit 3d4d0af
Show file tree
Hide file tree
Showing 12 changed files with 1,412 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.pq.android.library)
alias(libs.plugins.pq.android.hilt)
id("kotlinx-serialization")
}

android {
Expand All @@ -18,4 +19,6 @@ dependencies {
implementation(project(":core:network"))
implementation(project(":core:model"))
implementation(project(":core:datastore"))

implementation(libs.kotlinx.serialization.json)
}
2 changes: 2 additions & 0 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ secrets {
}

dependencies {
implementation(project(":core:common"))

// Okhttp Interceptor
implementation(libs.okhttp.logging)

Expand Down
486 changes: 486 additions & 0 deletions core/network/src/main/assets/images_page1.json

Large diffs are not rendered by default.

486 changes: 486 additions & 0 deletions core/network/src/main/assets/images_page2.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions core/network/src/main/assets/images_page_end.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"total": 7,
"totalHits": 7,
"hits": []
}
129 changes: 129 additions & 0 deletions core/network/src/main/assets/videos_page1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{
"total": 3,
"totalHits": 3,
"hits": [
{
"id": 26451,
"pageURL": "https://pixabay.com/videos/id-26451/",
"type": "film",
"tags": "cat, happy, animal",
"duration": 13,
"picture_id": "812497041-23341c0640e56f02b0026e5b218ed3d904c28c2659fc45b01f955081ae5bcf59-d",
"videos": {
"large": {
"url": "https://cdn.pixabay.com/vimeo/358778852/cat-26451.mp4?width=1920&hash=c8cdad290d1a1f4769d27507dd118d5fa516c4d8",
"width": 1920,
"height": 1080,
"size": 4880942
},
"medium": {
"url": "https://cdn.pixabay.com/vimeo/358778852/cat-26451.mp4?width=1280&hash=3881821c4ebfbcff7ad26565e0e7d4799d89489a",
"width": 1280,
"height": 720,
"size": 2400471
},
"small": {
"url": "https://cdn.pixabay.com/vimeo/358778852/cat-26451.mp4?width=960&hash=7c54108fa571d78b323b9354b13b0e2bb22f265a",
"width": 960,
"height": 540,
"size": 1606121
},
"tiny": {
"url": "https://cdn.pixabay.com/vimeo/358778852/cat-26451.mp4?width=640&hash=e31e3b41a6c9e838e934bfa9bcfc6c8d4686cf34",
"width": 640,
"height": 360,
"size": 671151
}
},
"views": 24055,
"downloads": 9349,
"likes": 92,
"comments": 20,
"user_id": 13034296,
"user": "talipozer",
"userImageURL": ""
},
{
"id": 2911,
"pageURL": "https://pixabay.com/videos/id-2911/",
"type": "film",
"tags": "cat, cats, lazy",
"duration": 20,
"picture_id": "568296387-20dc5252018653569acaab9576e70bc7c7e407eb9497db84db1f0a221c39e32d-d",
"videos": {
"large": {
"url": "https://cdn.pixabay.com/vimeo/164639743/cat-2911.mp4?width=1920&hash=ea47340c69dce271c915bf2bc6bb5efef3da797c",
"width": 1920,
"height": 1080,
"size": 11063802
},
"medium": {
"url": "https://cdn.pixabay.com/vimeo/164639743/cat-2911.mp4?width=1280&hash=438c8c8033af16e66a03c9236957e0ab82ccebea",
"width": 1280,
"height": 720,
"size": 6160427
},
"small": {
"url": "https://cdn.pixabay.com/vimeo/164639743/cat-2911.mp4?width=960&hash=75923149aa3c2e036435aa17abc45912a26cfa94",
"width": 960,
"height": 540,
"size": 3572267
},
"tiny": {
"url": "https://cdn.pixabay.com/vimeo/164639743/cat-2911.mp4?width=640&hash=e0685c1462618d5573e047d85022acbba86d8aa1",
"width": 640,
"height": 360,
"size": 1219438
}
},
"views": 18617,
"downloads": 10409,
"likes": 104,
"comments": 26,
"user_id": 1,
"user": "Pixabay",
"userImageURL": "https://cdn.pixabay.com/user/2014/10/13/11-29-23-818_250x250.png"
},
{
"id": 143654,
"pageURL": "https://pixabay.com/videos/id-143654/",
"type": "film",
"tags": "cat, kitten, stray cat",
"duration": 77,
"picture_id": "1574564044-6813360a2af587b3a9fbb58ec9497fd15f06a189129c18e044f52715eacf6ef0-d",
"videos": {
"large": {
"url": "https://cdn.pixabay.com/vimeo/784129635/cat-143654.mp4?width=1920&hash=b4f0f888802678d03b66ae5c7d0ed846314b88ab",
"width": 1920,
"height": 1080,
"size": 54308977
},
"medium": {
"url": "https://cdn.pixabay.com/vimeo/784129635/cat-143654.mp4?width=1280&hash=5cbce9ea3870804760bc923b0d3bfc33410f5a67",
"width": 1280,
"height": 720,
"size": 27164139
},
"small": {
"url": "https://cdn.pixabay.com/vimeo/784129635/cat-143654.mp4?width=960&hash=cc246ba7a09e075df9f8df0a0a0812faafcb7fa8",
"width": 960,
"height": 540,
"size": 16116099
},
"tiny": {
"url": "https://cdn.pixabay.com/vimeo/784129635/cat-143654.mp4?width=640&hash=e67bcab20be8278476ff35b83240c96401185701",
"width": 640,
"height": 360,
"size": 7567345
}
},
"views": 1988,
"downloads": 1096,
"likes": 29,
"comments": 1,
"user_id": 26479159,
"user": "colorful_square",
"userImageURL": "https://cdn.pixabay.com/user/2022/09/23/04-26-24-253_250x250.jpg"
}
]
}
5 changes: 5 additions & 0 deletions core/network/src/main/assets/videos_page_end.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"total": 3,
"totalHits": 3,
"hits": []
}
26 changes: 26 additions & 0 deletions core/network/src/main/java/JvmUnitTestFakeAssetManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import androidx.annotation.VisibleForTesting
import com.wei.picquest.core.network.fake.FakeAssetManager
import java.io.File
import java.io.InputStream
import java.util.Properties

/**
* This class helps with loading Android `/assets` files, especially when running JVM unit tests.
* It must remain on the root package for an easier [Class.getResource] with relative paths.
* @see <a href="https://developer.android.com/reference/tools/gradle-api/7.3/com/android/build/api/dsl/UnitTestOptions">UnitTestOptions</a>
*/
@VisibleForTesting
internal object JvmUnitTestFakeAssetManager : FakeAssetManager {
private val config =
requireNotNull(javaClass.getResource("com/android/tools/test_config.properties")) {
"""
Missing Android resources properties file.
Did you forget to enable the feature in the gradle build file?
android.testOptions.unitTests.isIncludeAndroidResources = true
""".trimIndent()
}
private val properties = Properties().apply { config.openStream().use(::load) }
private val assets = File(properties["android_merged_assets"].toString())

override fun open(fileName: String): InputStream = File(assets, fileName).inputStream()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.wei.picquest.core.network.fake

import java.io.InputStream

fun interface FakeAssetManager {
fun open(fileName: String): InputStream
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.wei.picquest.core.network.fake

import JvmUnitTestFakeAssetManager
import com.wei.picquest.core.network.Dispatcher
import com.wei.picquest.core.network.PqDispatchers
import com.wei.picquest.core.network.PqNetworkDataSource
import com.wei.picquest.core.network.model.NetworkSearchImages
import com.wei.picquest.core.network.model.NetworkSearchVideos
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import org.jetbrains.annotations.VisibleForTesting

class FakePqNetworkDataSource(
@Dispatcher(PqDispatchers.IO) private val ioDispatcher: CoroutineDispatcher,
private val networkJson: Json,
private val assets: FakeAssetManager = JvmUnitTestFakeAssetManager,
) : PqNetworkDataSource {

private var shouldReturnErrorForImages = false
private var shouldReturnErrorForVideos = false

@VisibleForTesting
fun setReturnErrorForImages(shouldReturnError: Boolean) {
shouldReturnErrorForImages = shouldReturnError
}

@VisibleForTesting
fun setReturnErrorForVideos(shouldReturnError: Boolean) {
shouldReturnErrorForVideos = shouldReturnError
}

@OptIn(ExperimentalSerializationApi::class)
override suspend fun searchImages(query: String, page: Int, perPage: Int): NetworkSearchImages =
withContext(ioDispatcher) {
if (shouldReturnErrorForImages) {
throw Exception("Fake exception for images")
}
when (page) {
0 -> assets.open(IMAGES_PAGE1_ASSET).use(networkJson::decodeFromStream)
1 -> assets.open(IMAGES_PAGE2_ASSET).use(networkJson::decodeFromStream)
else -> {
assets.open(IMAGES_PAGE_END_ASSET).use(networkJson::decodeFromStream)
}
}
}

@OptIn(ExperimentalSerializationApi::class)
override suspend fun searchVideos(query: String, page: Int, perPage: Int): NetworkSearchVideos =
withContext(ioDispatcher) {
if (shouldReturnErrorForVideos) {
throw Exception("Fake exception for images")
}
when (page) {
0 -> assets.open(VIDEOS_PAGE1_ASSET).use(networkJson::decodeFromStream)
else -> {
assets.open(VIDEOS_PAGE_END_ASSET).use(networkJson::decodeFromStream)
}
}
}

companion object {
private const val IMAGES_PAGE1_ASSET = "images_page1.json"
private const val IMAGES_PAGE2_ASSET = "images_page2.json"
private const val IMAGES_PAGE_END_ASSET = "images_page_end.json"
private const val VIDEOS_PAGE1_ASSET = "videos_page1.json"
private const val VIDEOS_PAGE_END_ASSET = "videos_page_end.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.wei.picquest.core.network.pagingsource

import JvmUnitTestFakeAssetManager
import androidx.paging.PagingSource
import com.google.common.truth.Truth.assertThat
import com.wei.picquest.core.network.fake.FakePqNetworkDataSource
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import org.junit.Before
import org.junit.Test

/**
* Unit tests for [PixabayImagePagingSource].
*
* 遵循此模型,安排、操作、斷言:
* {Arrange}{Act}{Assert}
*/
class PixabayImagePagingSourceTest {

private lateinit var fakePqNetworkDataSource: FakePqNetworkDataSource
private lateinit var pixabayImagePagingSource: PixabayImagePagingSource

private val testDispatcher = StandardTestDispatcher()

@Before
fun setUp() {
fakePqNetworkDataSource = FakePqNetworkDataSource(
ioDispatcher = testDispatcher,
networkJson = Json { ignoreUnknownKeys = true },
assets = JvmUnitTestFakeAssetManager,
)
pixabayImagePagingSource = PixabayImagePagingSource(fakePqNetworkDataSource, "testQuery")
}

@Test
fun `load should return non-empty page for first and second page`() = runTest(testDispatcher) {
// Arrange
val firstPageKey = 0
val secondPageKey = 1

// Act
val firstPageResult = pixabayImagePagingSource.load(
PagingSource.LoadParams.Refresh(
key = firstPageKey,
loadSize = 20,
placeholdersEnabled = false,
),
)
val secondPageResult = pixabayImagePagingSource.load(
PagingSource.LoadParams.Refresh(
key = secondPageKey,
loadSize = 20,
placeholdersEnabled = false,
),
)

// Assert
assertThat(firstPageResult).isInstanceOf(PagingSource.LoadResult.Page::class.java)
assertThat((firstPageResult as PagingSource.LoadResult.Page).data).isNotEmpty()
assertThat(secondPageResult).isInstanceOf(PagingSource.LoadResult.Page::class.java)
assertThat((secondPageResult as PagingSource.LoadResult.Page).data).isNotEmpty()
}

@Test
fun `load should return empty page at end of pagination`() = runTest(testDispatcher) {
// Arrange
val endPageKey = 2 // Assuming this is the end

// Act
val endPageResult = pixabayImagePagingSource.load(
PagingSource.LoadParams.Refresh(
key = endPageKey,
loadSize = 20,
placeholdersEnabled = false,
),
)

// Assert
assertThat(endPageResult).isInstanceOf(PagingSource.LoadResult.Page::class.java)
assertThat((endPageResult as PagingSource.LoadResult.Page).data).isEmpty()
}

@Test
fun `load should return error when data source throws exception`() = runTest {
// Arrange
fakePqNetworkDataSource.setReturnErrorForImages(true)

// Act
val result = pixabayImagePagingSource.load(
PagingSource.LoadParams.Refresh(
key = 0,
loadSize = 20,
placeholdersEnabled = false,
),
)

// Assert
assertThat(result).isInstanceOf(PagingSource.LoadResult.Error::class.java)
}
}
Loading

0 comments on commit 3d4d0af

Please sign in to comment.