# Unit Testing with Mockito
###### tags: `Android Unit Testing` `Mockito`
[TOC]
# What are unit testing?
1. Automated
1. Only test business logic
>**Note:
>There should not be android specific code/views in these tests** [color=red]
# Where to locate unit test in Android?

* androidTest is an interfaceTest
* test is unit test (Only logic testing)
# Gradle.Build (App) setup
```kotlin=
testImplementation 'android.arch.core:core-testing:1.1.1'
```
# Implementation
## New Test
New a file class in **test** folder(**NOT** androidTest).
## Different Annotations
We will have
### **@get:Rule**
This one describes rules that the test will follow.
In this case, we used **InstantTaskExecutorRule()**, this one will have error if Gradle.Build(App) is not set up with testImplementation.
```kotlin=
@get:Rule
var rule = InstantTaskExecutorRule()
```
**What is InstantTaskExecutorRule?**
InstantTaskExecutorRule swaps the background executor used by the Architecture Components with a different one which executes each task synchronously. So when you need it especially when writing a unit test, you need to implement testImplementation dependency.
### **@Before**
Those with this annotation, means that they will have to be run before the test.
In this case mainThread needs to be dealed, as it is related to main Thread(UI Thread).
```kotlin=
@Before
fun setUpRxSchedulers(){
//When Observable is called, we want to return immediately (0 delay)
val immediate = object : Scheduler() {
override fun scheduleDirect(run: Runnable?, delay: Long, unit: TimeUnit?): Disposable {
//0 for delay, as we do not want to wait when calling schedulers
return super.scheduleDirect(run, 0, unit)
}
override fun createWorker(): Worker {
return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
}
}
RxJavaPlugins.setInitIoSchedulerHandler { immediate }
RxJavaPlugins.setInitComputationSchedulerHandler { immediate }
RxJavaPlugins.setInitNewThreadSchedulerHandler { immediate }
RxJavaPlugins.setInitSingleSchedulerHandler { immediate }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediate }
}
```
### **@Mock** && **@InjectMocks**
**Introduction to Mock:**
A mock object might assert the order in which its methods are called, or **assert consistency of data** across method calls.
**How to use?**
**@Mock**
We have to first deal whose variables that we will be using and annotating them with **@Mock** to assert that this variable is present and injected.
For those that we will be creating them, such as dummy data, we do not annotate with @Mock.
**@InjectMocks**
But also we need to know where to use those mocks, so we will have **@InjectMocks** to specify where they will be put.
**MockitoAnnotations.initMocks**
We need to rememeber to initiate the mocks before the tests in order to use them.
In this case countryService is used in ListViewModel Class.
```kotlin=
@Mock
lateinit var countryService : CountryService
@InjectMocks
var listViewModel = ListViewModel()
private var testSingle : Single<ArrayList<Country>>? = null
@Before
fun setUp(){
MockitoAnnotations.initMocks(this)
}
```
**Note:**
Without @Mock annotation for injected variables/lateinit var, we will face errors like this below.

### **@Test**
**Single.just(Result)**
Can Either be a real result or Throwable to test fail api call.
**Mockito.when (\`when`)**
When(Do this).thenReturn(the result you want)
**Assert.assertEquals**
This will be used to check the finishing value result for each of the variables. If the result does not fit the expected one, test will fail.
```kotlin=
@Test
fun getCountriesSuccess(){
val country : Country = Country("countryName", "capital", "url")
val countryList : ArrayList<Country> = arrayListOf(country)
//Can test success Api: It tell us it returns countryList
testSingle = Single.just(countryList)
//Mockito.when
`when`(countryService.getCountries()).thenReturn(testSingle)
listViewModel.refresh()
//Write all expected results, if the outcome is different then test will fail
Assert.assertEquals(1, listViewModel.countryList.value?.size)
Assert.assertEquals(false, listViewModel.loadError.value)
Assert.assertEquals(false, listViewModel.loading.value)
//Right click on method and run test to check the result
}
@Test
fun getCountriesFail(){
//Can test error Api
testSingle = Single.error(Throwable())
//Mockito.when
`when`(countryService.getCountries()).thenReturn(testSingle)
listViewModel.refresh()
//Write all expected results, if the outcome is different then test will fail
Assert.assertEquals(null, listViewModel.countryList.value?.size)
Assert.assertEquals(true, listViewModel.loadError.value)
Assert.assertEquals(false, listViewModel.loading.value)
}
```
## Complete Test
```kotlin=
class ListViewModelTest {
@get:Rule
var rule = InstantTaskExecutorRule()
@Mock
lateinit var countryService : CountryService
@InjectMocks
var listViewModel = ListViewModel()
private var testSingle : Single<ArrayList<Country>>? = null
@Before
fun setUp(){
MockitoAnnotations.initMocks(this)
}
@Test
fun getCountriesSuccess(){
val country : Country = Country("countryName", "capital", "url")
val countryList : ArrayList<Country> = arrayListOf(country)
//Can test success Api: It tell us it returns countryList
testSingle = Single.just(countryList)
//Mockito.when
`when`(countryService.getCountries()).thenReturn(testSingle)
listViewModel.refresh()
//Write all expected results, if the outcome is different then test will fail
Assert.assertEquals(1, listViewModel.countryList.value?.size)
Assert.assertEquals(false, listViewModel.loadError.value)
Assert.assertEquals(false, listViewModel.loading.value)
//Right click on method and run test to check the result
}
@Test
fun getCountriesFail(){
//Can test error Api
testSingle = Single.error(Throwable())
//Mockito.when
`when`(countryService.getCountries()).thenReturn(testSingle)
listViewModel.refresh()
//Write all expected results, if the outcome is different then test will fail
Assert.assertEquals(null, listViewModel.countryList.value?.size)
Assert.assertEquals(true, listViewModel.loadError.value)
Assert.assertEquals(false, listViewModel.loading.value)
}
@Before
fun setUpRxSchedulers(){
val immediate = object : Scheduler() {
override fun scheduleDirect(run: Runnable?, delay: Long, unit: TimeUnit?): Disposable {
//0 for delay, as we do not want to wait when calling schedulers
return super.scheduleDirect(run, 0, unit)
}
override fun createWorker(): Worker {
return ExecutorScheduler.ExecutorWorker(Executor { it.run() })
}
}
RxJavaPlugins.setInitIoSchedulerHandler { immediate }
RxJavaPlugins.setInitComputationSchedulerHandler { immediate }
RxJavaPlugins.setInitNewThreadSchedulerHandler { immediate }
RxJavaPlugins.setInitSingleSchedulerHandler { immediate }
RxAndroidPlugins.setInitMainThreadSchedulerHandler { immediate }
}
}
```
## Imports used
```kotlin===
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import io.reactivex.Scheduler
import io.reactivex.Single
import io.reactivex.android.plugins.RxAndroidPlugins
import io.reactivex.disposables.Disposable
import io.reactivex.internal.schedulers.ExecutorScheduler
import io.reactivex.plugins.RxJavaPlugins
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import udemy.kotlin.countries.model.Country
import udemy.kotlin.countries.model.CountryService
import udemy.kotlin.countries.viewmodel.ListViewModel
import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
```
# Note: **AndroidSchedulers.mainThread()**
**AndroidSchedulers.mainThread()** is not part of an Android System, but it is a way to access the main thread that will run on a device. But on tests, we do not want it.