mirror of
https://github.com/hmalik144/MovieListTest.git
synced 2025-12-10 01:25:18 +00:00
Updated unit tests
This commit is contained in:
@@ -58,6 +58,10 @@ dependencies {
|
|||||||
//mock websever for testing retrofit responses
|
//mock websever for testing retrofit responses
|
||||||
testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0"
|
testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0"
|
||||||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
|
||||||
|
// Mockk
|
||||||
|
def mockk_ver = "1.10.2"
|
||||||
|
testImplementation "io.mockk:mockk:$mockk_ver"
|
||||||
|
androidTestImplementation "io.mockk:mockk-android:$mockk_ver"
|
||||||
|
|
||||||
//mockito and livedata testing
|
//mockito and livedata testing
|
||||||
testImplementation 'org.mockito:mockito-inline:2.13.0'
|
testImplementation 'org.mockito:mockito-inline:2.13.0'
|
||||||
@@ -90,4 +94,7 @@ dependencies {
|
|||||||
|
|
||||||
// Circle Image View
|
// Circle Image View
|
||||||
implementation 'com.mikhaellopez:circularimageview:4.2.0'
|
implementation 'com.mikhaellopez:circularimageview:4.2.0'
|
||||||
|
|
||||||
|
// extra
|
||||||
|
testImplementation 'org.json:json:20180813'
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ import org.junit.Test
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class MoviesRoomDatabaseTest{
|
class MoviesRoomDatabaseTest{
|
||||||
private lateinit var simpleDao: SimpleDao
|
private lateinit var simpleDao: SimpleDao
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.io.IOException
|
|||||||
* Abstract class for extracting <T> from Retrofit Response<T>
|
* Abstract class for extracting <T> from Retrofit Response<T>
|
||||||
* Or throw IOException if the API call fails
|
* Or throw IOException if the API call fails
|
||||||
*/
|
*/
|
||||||
abstract class ResponseUnwrap {
|
abstract class SafeApiCall {
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
suspend fun <T : Any> responseUnwrap(
|
suspend fun <T : Any> responseUnwrap(
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.example.h_mal.movielisttest.data.repository
|
package com.example.h_mal.movielisttest.data.repository
|
||||||
|
|
||||||
import com.example.h_mal.movielisttest.data.network.MoviesApi
|
import com.example.h_mal.movielisttest.data.network.MoviesApi
|
||||||
import com.example.h_mal.movielisttest.data.network.networkUtils.ResponseUnwrap
|
import com.example.h_mal.movielisttest.data.network.networkUtils.SafeApiCall
|
||||||
import com.example.h_mal.movielisttest.data.network.response.MoviesResponse
|
import com.example.h_mal.movielisttest.data.network.response.MoviesResponse
|
||||||
import com.example.h_mal.movielisttest.data.network.response.ResultsItem
|
import com.example.h_mal.movielisttest.data.network.response.ResultsItem
|
||||||
import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider
|
import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider
|
||||||
@@ -12,7 +12,7 @@ class RepositoryImpl(
|
|||||||
private val api: MoviesApi,
|
private val api: MoviesApi,
|
||||||
private val database: MoviesRoomDatabase,
|
private val database: MoviesRoomDatabase,
|
||||||
private val preferences: PreferenceProvider
|
private val preferences: PreferenceProvider
|
||||||
) : Repository, ResponseUnwrap() {
|
) : Repository, SafeApiCall() {
|
||||||
|
|
||||||
|
|
||||||
override suspend fun getMoviesFromApi(pageNumber: Int): MoviesResponse? {
|
override suspend fun getMoviesFromApi(pageNumber: Int): MoviesResponse? {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
|
||||||
import com.example.h_mal.movielisttest.R
|
import com.example.h_mal.movielisttest.R
|
||||||
import com.example.h_mal.movielisttest.utils.*
|
import com.example.h_mal.movielisttest.utils.*
|
||||||
import kotlinx.android.synthetic.main.empty_view_item.view.*
|
import kotlinx.android.synthetic.main.empty_view_item.view.*
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.example.h_mal.movielisttest.R
|
import com.example.h_mal.movielisttest.R
|
||||||
import com.example.h_mal.movielisttest.data.models.Movie
|
import com.example.h_mal.movielisttest.data.models.Movie
|
||||||
import com.example.h_mal.movielisttest.utils.loadImage
|
import com.example.h_mal.movielisttest.utils.loadImage
|
||||||
import com.squareup.picasso.Picasso
|
|
||||||
import kotlinx.android.synthetic.main.item_layout.view.*
|
import kotlinx.android.synthetic.main.item_layout.view.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.view.View
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.example.h_mal.movielisttest.R
|
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
fun View.show() {
|
fun View.show() {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.example.h_mal.movielisttest.data.network.networkUtils
|
||||||
|
|
||||||
|
import com.example.h_mal.movielisttest.data.network.response.MoviesResponse
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
|
import org.junit.Test
|
||||||
|
import retrofit2.Response
|
||||||
|
import java.io.IOException
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
class SafeApiCallTest: SafeApiCall(){
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun successfulResponse_SuccessfulOutput() = runBlocking{
|
||||||
|
// GIVEN
|
||||||
|
val mockApiResponse = mockk<MoviesResponse>()
|
||||||
|
val mockResponse = Response.success(mockApiResponse)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
val result = responseUnwrap { mockResponse }
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
assertNotNull(result)
|
||||||
|
assertEquals(mockApiResponse, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun unsuccessfulResponse_thrownOutput() = runBlocking{
|
||||||
|
// GIVEN
|
||||||
|
val errorMessage = "{\n" +
|
||||||
|
" \"status_code\": 7,\n" +
|
||||||
|
" \"status_message\": \"Invalid API key: You must be granted a valid key.\",\n" +
|
||||||
|
" \"success\": false\n" +
|
||||||
|
"}"
|
||||||
|
|
||||||
|
val errorResponseBody = errorMessage.toResponseBody("application/json".toMediaTypeOrNull())
|
||||||
|
val mockResponse = Response.error<String>(404, errorResponseBody)
|
||||||
|
|
||||||
|
//THEN - assert exception is not null
|
||||||
|
val ioExceptionReturned = assertFailsWith<IOException> {
|
||||||
|
responseUnwrap { mockResponse }!!
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(ioExceptionReturned)
|
||||||
|
assertEquals(ioExceptionReturned.message, "Invalid API key: You must be granted a valid key.")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,8 @@ import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider
|
|||||||
import com.example.h_mal.movielisttest.data.room.MoviesRoomDatabase
|
import com.example.h_mal.movielisttest.data.room.MoviesRoomDatabase
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
|||||||
@@ -2,16 +2,12 @@ package com.example.h_mal.movielisttest.ui.main
|
|||||||
|
|
||||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.test.espresso.idling.CountingIdlingResource
|
|
||||||
import com.example.h_mal.movielisttest.application.MovieListApplication.Companion.idlingResources
|
|
||||||
import com.example.h_mal.movielisttest.data.network.response.MoviesResponse
|
import com.example.h_mal.movielisttest.data.network.response.MoviesResponse
|
||||||
import com.example.h_mal.movielisttest.data.repository.Repository
|
import com.example.h_mal.movielisttest.data.repository.Repository
|
||||||
import com.example.h_mal.movielisttest.data.room.MovieEntity
|
import com.example.h_mal.movielisttest.data.room.MovieEntity
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Assert.*
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -20,7 +16,8 @@ import org.mockito.Mock
|
|||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import javax.annotation.meta.When
|
|
||||||
|
|
||||||
|
|
||||||
class MainViewModelTest {
|
class MainViewModelTest {
|
||||||
|
|
||||||
@@ -32,9 +29,6 @@ class MainViewModelTest {
|
|||||||
@Mock
|
@Mock
|
||||||
lateinit var repository: Repository
|
lateinit var repository: Repository
|
||||||
|
|
||||||
@Mock
|
|
||||||
lateinit var observer: Observer<List<MovieEntity>>
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
@@ -55,12 +49,9 @@ class MainViewModelTest {
|
|||||||
|
|
||||||
//THEN
|
//THEN
|
||||||
viewModel.loadMovies()
|
viewModel.loadMovies()
|
||||||
delay(200)
|
delay(50)
|
||||||
viewModel.operationState.observeForever{
|
|
||||||
it.getContentIfNotHandled()?.let {result ->
|
kotlin.test.assertFalse { viewModel.operationState.value?.getContentIfNotHandled()!! }
|
||||||
kotlin.test.assertFalse { result }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -70,11 +61,8 @@ class MainViewModelTest {
|
|||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
viewModel.loadMovies()
|
viewModel.loadMovies()
|
||||||
viewModel.operationError.observeForever{
|
delay(50)
|
||||||
it.getContentIfNotHandled()?.let {result ->
|
assertEquals(viewModel.operationError.value?.getContentIfNotHandled()!!, "throwed")
|
||||||
assertEquals(result, "throwed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -83,30 +71,25 @@ class MainViewModelTest {
|
|||||||
val mockApiResponse = Mockito.mock(MoviesResponse::class.java)
|
val mockApiResponse = Mockito.mock(MoviesResponse::class.java)
|
||||||
|
|
||||||
//WHEN
|
//WHEN
|
||||||
Mockito.`when`(repository.getMoviesFromApi(2)).thenReturn(mockApiResponse)
|
|
||||||
Mockito.`when`(repository.getCurrentPage()).thenReturn(2)
|
Mockito.`when`(repository.getCurrentPage()).thenReturn(2)
|
||||||
|
Mockito.`when`(repository.getMoviesFromApi(2)).thenReturn(mockApiResponse)
|
||||||
|
|
||||||
//THEN
|
//THEN
|
||||||
viewModel.loadMovies()
|
viewModel.loadMoreMovies()
|
||||||
delay(200)
|
delay(50)
|
||||||
viewModel.operationState.observeForever{
|
kotlin.test.assertFalse { viewModel.operationState.value?.getContentIfNotHandled()!! }
|
||||||
it.getContentIfNotHandled()?.let {result ->
|
|
||||||
kotlin.test.assertFalse { result }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getMoreFromRepository_unsuccessfulReturn() = runBlocking{
|
fun getMoreFromRepository_unsuccessfulReturn() = runBlocking{
|
||||||
// WHEN
|
// WHEN
|
||||||
|
Mockito.`when`(repository.getCurrentPage()).thenReturn(2)
|
||||||
Mockito.`when`(repository.getMoviesFromApi(2)).thenAnswer{ throw IOException("throwed") }
|
Mockito.`when`(repository.getMoviesFromApi(2)).thenAnswer{ throw IOException("throwed") }
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
viewModel.loadMovies()
|
viewModel.loadMoreMovies()
|
||||||
viewModel.operationError.observeForever{
|
delay(50)
|
||||||
it.getContentIfNotHandled()?.let {result ->
|
assertEquals(viewModel.operationError.value?.getContentIfNotHandled()!!, "throwed")
|
||||||
assertEquals(result, "throwed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user