Testing Repositories

This commit is contained in:
2021-09-09 00:20:01 +02:00
parent 76330854c0
commit 73ae6df075
8 changed files with 310 additions and 19 deletions
@@ -1,17 +0,0 @@
package com.ericampire.android.androidstudycase
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
@@ -0,0 +1,25 @@
package com.ericampire.android.androidstudycase.common
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.api.extension.ParameterContext
import org.junit.jupiter.api.extension.ParameterResolver
@ExperimentalCoroutinesApi
class CoroutineDispatcherExtension : ParameterResolver {
override fun supportsParameter(
parameterContext: ParameterContext,
extensionContext: ExtensionContext?
): Boolean {
return parameterContext.parameter.type.equals(TestCoroutineDispatcher::class.java)
}
override fun resolveParameter(
parameterContext: ParameterContext?,
extensionContext: ExtensionContext?
): Any {
return TestCoroutineDispatcher()
}
}
@@ -0,0 +1,24 @@
package com.ericampire.android.androidstudycase.common
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.api.extension.ParameterContext
import org.junit.jupiter.api.extension.ParameterResolver
@ExperimentalCoroutinesApi
class CoroutineScopeExtension : ParameterResolver {
override fun supportsParameter(
parameterContext: ParameterContext,
extensionContext: ExtensionContext?
): Boolean {
return parameterContext.parameter.type.equals(TestCoroutineScope::class.java)
}
override fun resolveParameter(
parameterContext: ParameterContext?,
extensionContext: ExtensionContext?
): Any {
return TestCoroutineScope()
}
}
@@ -0,0 +1,25 @@
package com.ericampire.android.androidstudycase.common
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.jupiter.api.extension.AfterAllCallback
import org.junit.jupiter.api.extension.BeforeAllCallback
import org.junit.jupiter.api.extension.ExtensionContext
@ExperimentalCoroutinesApi
class MainCoroutineExtension : BeforeAllCallback, AfterAllCallback {
private val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
override fun beforeAll(context: ExtensionContext?) {
Dispatchers.setMain(testDispatcher)
}
override fun afterAll(context: ExtensionContext?) {
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
}
@@ -61,8 +61,8 @@ class AnimatorRepositoryTest(
assertEquals(it.data, PreviewData.Animator.data) assertEquals(it.data, PreviewData.Animator.data)
} }
coVerify { verify(exactly = 1) { remoteDataSource.findAll() }
remoteDataSource.findAll() coVerify(exactly = PreviewData.Animator.data.size) {
localDataSource.save(any()) localDataSource.save(any())
} }
} }
@@ -0,0 +1,68 @@
package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.common.CoroutineDispatcherExtension
import com.ericampire.android.androidstudycase.common.CoroutineScopeExtension
import com.ericampire.android.androidstudycase.common.MainCoroutineExtension
import com.ericampire.android.androidstudycase.data.datasource.blog.BlogDataSource
import com.ericampire.android.androidstudycase.util.PreviewData
import com.ericampire.android.androidstudycase.util.Result
import com.ericampire.android.androidstudycase.util.data
import io.mockk.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import kotlin.time.ExperimentalTime
@ExperimentalCoroutinesApi
@ExtendWith(
value = [
MainCoroutineExtension::class,
CoroutineDispatcherExtension::class,
CoroutineScopeExtension::class
]
)
class BlogRepositoryTest(
private val coroutineScope: TestCoroutineScope,
private val dispatcher: TestCoroutineDispatcher
) {
// SUT
private lateinit var blogRepository: BlogRepositoryImpl
// DOC's
private val remoteDataSource = mockk<BlogDataSource>(relaxed = true)
private val localDataSource = mockk<BlogDataSource>(relaxed = true)
@BeforeEach
fun setup() {
blogRepository = BlogRepositoryImpl(
remoteDataSource = remoteDataSource,
localDataSource = localDataSource,
coroutineScope = coroutineScope,
coroutineDispatcher = dispatcher
)
}
@ExperimentalTime
@Test
fun findingAllStories() = runBlockingTest {
every { remoteDataSource.findAll() } returns flowOf(Result.Success(PreviewData.Blog.data))
coEvery { localDataSource.save(any()) } just Runs
blogRepository.findAll().collect {
Assert.assertEquals(it.data, PreviewData.Blog.data)
}
verify(exactly = 1) { remoteDataSource.findAll() }
coVerify(exactly = PreviewData.Blog.data.size) {
localDataSource.save(any())
}
}
}
@@ -0,0 +1,100 @@
package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.common.CoroutineDispatcherExtension
import com.ericampire.android.androidstudycase.common.CoroutineScopeExtension
import com.ericampire.android.androidstudycase.common.MainCoroutineExtension
import com.ericampire.android.androidstudycase.data.datasource.lottiefiles.LottieFileDataSource
import com.ericampire.android.androidstudycase.util.PreviewData
import com.ericampire.android.androidstudycase.util.Result
import com.ericampire.android.androidstudycase.util.data
import io.mockk.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import kotlin.time.ExperimentalTime
@ExperimentalCoroutinesApi
@ExtendWith(
value = [
MainCoroutineExtension::class,
CoroutineDispatcherExtension::class,
CoroutineScopeExtension::class
]
)
class LottieFileRepositoryTest(
private val coroutineScope: TestCoroutineScope,
private val dispatcher: TestCoroutineDispatcher
) {
// SUT
private lateinit var repository: LottieFileRepositoryImpl
// DOC's
private val remoteDataSource = mockk<LottieFileDataSource>(relaxed = true)
private val localDataSource = mockk<LottieFileDataSource>(relaxed = true)
@BeforeEach
fun setup() {
repository = LottieFileRepositoryImpl(
remoteDataSource = remoteDataSource,
localDataSource = localDataSource,
coroutineScope = coroutineScope,
coroutineDispatcher = dispatcher
)
}
@ExperimentalTime
@Test
fun findingFeaturedAnimation() = runBlockingTest {
every { remoteDataSource.findFeatured() } returns flowOf(Result.Success(PreviewData.Lottiefile.data))
coEvery { localDataSource.save(any()) } just Runs
repository.findFeatured().collect {
Assert.assertEquals(it.data, PreviewData.Lottiefile.data)
}
verify(exactly = 1) { remoteDataSource.findFeatured() }
coVerify(exactly = PreviewData.Lottiefile.data.size) {
localDataSource.save(any())
}
}
@ExperimentalTime
@Test
fun findingRecentAnimation() = runBlockingTest {
every { remoteDataSource.findRecent() } returns flowOf(Result.Success(PreviewData.Lottiefile.data))
coEvery { localDataSource.save(any()) } just Runs
repository.findRecent().collect {
Assert.assertEquals(it.data, PreviewData.Lottiefile.data)
}
verify(exactly = 1) { remoteDataSource.findRecent() }
coVerify(exactly = PreviewData.Lottiefile.data.size) {
localDataSource.save(any())
}
}
@ExperimentalTime
@Test
fun findingPopularAnimation() = runBlockingTest {
every { remoteDataSource.findPopular() } returns flowOf(Result.Success(PreviewData.Lottiefile.data))
coEvery { localDataSource.save(any()) } just Runs
repository.findPopular().collect {
Assert.assertEquals(it.data, PreviewData.Lottiefile.data)
}
verify(exactly = 1) { remoteDataSource.findPopular() }
coVerify(exactly = PreviewData.Lottiefile.data.size) {
localDataSource.save(any())
}
}
}
@@ -0,0 +1,66 @@
package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.common.CoroutineDispatcherExtension
import com.ericampire.android.androidstudycase.common.CoroutineScopeExtension
import com.ericampire.android.androidstudycase.common.MainCoroutineExtension
import com.ericampire.android.androidstudycase.data.datasource.user.UserDataSource
import com.ericampire.android.androidstudycase.util.PreviewData
import com.ericampire.android.androidstudycase.util.Result
import com.ericampire.android.androidstudycase.util.data
import io.mockk.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ExperimentalCoroutinesApi
@ExtendWith(
value = [
MainCoroutineExtension::class,
CoroutineDispatcherExtension::class,
CoroutineScopeExtension::class
]
)
class UserRepositoryTest(
private val coroutineScope: TestCoroutineScope,
private val dispatcher: TestCoroutineDispatcher
) {
// SUT
private lateinit var repository: UserRepositoryImpl
// DOC's
private val localDataSource = mockk<UserDataSource>(relaxed = true)
@BeforeEach
fun setup() {
repository = UserRepositoryImpl(localDataSource)
}
@Test
fun findCurrentUser() = runBlockingTest {
every { localDataSource.findAll() } returns flowOf(Result.Success(PreviewData.User.data))
repository.findAll().collect {
Assert.assertEquals(it.data, PreviewData.User.data)
}
verify(exactly = 1) { localDataSource.findAll() }
}
@Test
fun saveUser() = runBlockingTest {
coEvery { localDataSource.save(PreviewData.User.data.first()) } just Runs
repository.save(PreviewData.User.data.first())
coVerify(exactly = 1) {
localDataSource.save(PreviewData.User.data.first())
}
}
}