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
|
||||
testImplementation "com.squareup.okhttp3:mockwebserver:4.6.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
|
||||
testImplementation 'org.mockito:mockito-inline:2.13.0'
|
||||
@@ -90,4 +94,7 @@ dependencies {
|
||||
|
||||
// Circle Image View
|
||||
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 java.io.IOException
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MoviesRoomDatabaseTest{
|
||||
private lateinit var simpleDao: SimpleDao
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.io.IOException
|
||||
* Abstract class for extracting <T> from Retrofit Response<T>
|
||||
* Or throw IOException if the API call fails
|
||||
*/
|
||||
abstract class ResponseUnwrap {
|
||||
abstract class SafeApiCall {
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
suspend fun <T : Any> responseUnwrap(
|
||||
@@ -1,7 +1,7 @@
|
||||
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.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.ResultsItem
|
||||
import com.example.h_mal.movielisttest.data.prefs.PreferenceProvider
|
||||
@@ -12,7 +12,7 @@ class RepositoryImpl(
|
||||
private val api: MoviesApi,
|
||||
private val database: MoviesRoomDatabase,
|
||||
private val preferences: PreferenceProvider
|
||||
) : Repository, ResponseUnwrap() {
|
||||
) : Repository, SafeApiCall() {
|
||||
|
||||
|
||||
override suspend fun getMoviesFromApi(pageNumber: Int): MoviesResponse? {
|
||||
|
||||
@@ -7,7 +7,6 @@ import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.example.h_mal.movielisttest.R
|
||||
import com.example.h_mal.movielisttest.utils.*
|
||||
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.data.models.Movie
|
||||
import com.example.h_mal.movielisttest.utils.loadImage
|
||||
import com.squareup.picasso.Picasso
|
||||
import kotlinx.android.synthetic.main.item_layout.view.*
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.h_mal.movielisttest.R
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
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 kotlinx.coroutines.runBlocking
|
||||
import okhttp3.ResponseBody
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
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.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.repository.Repository
|
||||
import com.example.h_mal.movielisttest.data.room.MovieEntity
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -20,7 +16,8 @@ import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.io.IOException
|
||||
import javax.annotation.meta.When
|
||||
|
||||
|
||||
|
||||
class MainViewModelTest {
|
||||
|
||||
@@ -32,9 +29,6 @@ class MainViewModelTest {
|
||||
@Mock
|
||||
lateinit var repository: Repository
|
||||
|
||||
@Mock
|
||||
lateinit var observer: Observer<List<MovieEntity>>
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
@@ -55,12 +49,9 @@ class MainViewModelTest {
|
||||
|
||||
//THEN
|
||||
viewModel.loadMovies()
|
||||
delay(200)
|
||||
viewModel.operationState.observeForever{
|
||||
it.getContentIfNotHandled()?.let {result ->
|
||||
kotlin.test.assertFalse { result }
|
||||
}
|
||||
}
|
||||
delay(50)
|
||||
|
||||
kotlin.test.assertFalse { viewModel.operationState.value?.getContentIfNotHandled()!! }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,11 +61,8 @@ class MainViewModelTest {
|
||||
|
||||
// THEN
|
||||
viewModel.loadMovies()
|
||||
viewModel.operationError.observeForever{
|
||||
it.getContentIfNotHandled()?.let {result ->
|
||||
assertEquals(result, "throwed")
|
||||
}
|
||||
}
|
||||
delay(50)
|
||||
assertEquals(viewModel.operationError.value?.getContentIfNotHandled()!!, "throwed")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,30 +71,25 @@ class MainViewModelTest {
|
||||
val mockApiResponse = Mockito.mock(MoviesResponse::class.java)
|
||||
|
||||
//WHEN
|
||||
Mockito.`when`(repository.getMoviesFromApi(2)).thenReturn(mockApiResponse)
|
||||
Mockito.`when`(repository.getCurrentPage()).thenReturn(2)
|
||||
Mockito.`when`(repository.getMoviesFromApi(2)).thenReturn(mockApiResponse)
|
||||
|
||||
//THEN
|
||||
viewModel.loadMovies()
|
||||
delay(200)
|
||||
viewModel.operationState.observeForever{
|
||||
it.getContentIfNotHandled()?.let {result ->
|
||||
kotlin.test.assertFalse { result }
|
||||
}
|
||||
}
|
||||
viewModel.loadMoreMovies()
|
||||
delay(50)
|
||||
kotlin.test.assertFalse { viewModel.operationState.value?.getContentIfNotHandled()!! }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getMoreFromRepository_unsuccessfulReturn() = runBlocking{
|
||||
// WHEN
|
||||
Mockito.`when`(repository.getCurrentPage()).thenReturn(2)
|
||||
Mockito.`when`(repository.getMoviesFromApi(2)).thenAnswer{ throw IOException("throwed") }
|
||||
|
||||
// THEN
|
||||
viewModel.loadMovies()
|
||||
viewModel.operationError.observeForever{
|
||||
it.getContentIfNotHandled()?.let {result ->
|
||||
assertEquals(result, "throwed")
|
||||
}
|
||||
}
|
||||
viewModel.loadMoreMovies()
|
||||
delay(50)
|
||||
assertEquals(viewModel.operationError.value?.getContentIfNotHandled()!!, "throwed")
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user