0

I am trying to unit test my repository . In that i want to write test for function which makes api calls.(function name :- searchImage) The function calls datasource for actual api calls. I am using a fake data source which extends from the shopping data source interface. How can i provide different responses from fake data source for the api calls like no internet , Null body or Success response.

ShoppingRepositoryInterface

interface ShoppingRepository {

    suspend fun insertShoppingItem(shoppingItem: ShoppingItem)

    suspend fun deleteShoppingItem(shoppingItem: ShoppingItem)

    fun getAllShoppingItems() : LiveData<List<ShoppingItem>>

    fun getTotalPrice() : LiveData<Float>

    suspend fun searchImage(q:String) : Resource<ImageResponse>
}

ShoppingRepositoryImpl

@ViewModelScoped
class ShoppingRepositoryImpl @Inject constructor(
    private val dataSource: ShoppingDataSource
) : ShoppingRepository{

    override suspend fun insertShoppingItem(shoppingItem: ShoppingItem) = dataSource.insertShoppingItem(shoppingItem)

    override suspend fun deleteShoppingItem(shoppingItem: ShoppingItem) = dataSource.deleteShoppingItem(shoppingItem)

    override fun getAllShoppingItems() = dataSource.getAllShoppingItems()

    override fun getTotalPrice() = dataSource.getTotalPrice()

    override suspend fun searchImage(q: String) : Resource<ImageResponse> {
        return try {
            val response = dataSource.searchImage(q)
            if(response.isSuccessful){
                response.body()?.let {
                    Resource.Success(it)
                }?:Resource.Error("Some Error Occurred")
            }else{
                Resource.Error("Some Error Occurred")
            }
        }catch (e:Exception){
            Resource.Error("Couldn't connect to the server.Please try later")
        }
    }

}

ShoppingReposositoryTest

class ShoppingRepositoryTest{

    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()


    private lateinit var repository: ShoppingRepository
    private lateinit var dataSource: ShoppingDataSource
    private val shoppingItem1 = ShoppingItem("name1",1,price=1f,"url1",1)
    private val shoppingItem2 = ShoppingItem("name2",2,price=2f,"url2",2)
    private val shoppingItem3 = ShoppingItem("name3",3,price=3f,"url3",3)

    @Before
    fun setup(){
        dataSource = FakeDataSource(mutableListOf(
            shoppingItem1
        ))
        repository = ShoppingRepositoryImpl(dataSource)
    }

    @Test
    @ExperimentalCoroutinesApi
    fun insertShoppingItem_returnsWhetherItemInserted() = runTest{
        //Given

        //When
       repository.insertShoppingItem(shoppingItem2)
        val shoppingList = repository.getAllShoppingItems().getOrAwaitValue()

        //Then
        assertThat(shoppingList).contains(shoppingItem1)
    }

    @Test
    @ExperimentalCoroutinesApi
    fun deleteShoppingItem_returnsWhetherItemDeleted() = runTest{
        //Given


        //When
        repository.deleteShoppingItem(shoppingItem1)
        val shoppingList = repository.getAllShoppingItems().getOrAwaitValue()

        //Then
        assertThat(shoppingList.contains(shoppingItem1)).isFalse()
    }

    @Test
    @ExperimentalCoroutinesApi
    fun observeTotalPrice_returnsTotalPrice() = runTest {
        //Given


        //When
        repository.insertShoppingItem(shoppingItem2)
        repository.insertShoppingItem(shoppingItem3)
        val actual = repository.getTotalPrice().getOrAwaitValue()
        val expected = 14f

        //Then
        assertThat(expected).isEqualTo(actual)
    }

    @Test
    @ExperimentalCoroutinesApi
    fun observesSearchImage_returnsNoInternetError() = runTest {
        //Given

        //When

    }

ShoppingDataSourceInterface

interface ShoppingDataSource {

    suspend fun insertShoppingItem(shoppingItem:ShoppingItem)

    suspend fun deleteShoppingItem(shoppingItem: ShoppingItem)

    fun getAllShoppingItems() : LiveData<List<ShoppingItem>>

    fun getTotalPrice() : LiveData<Float>

    suspend fun searchImage(q:String) : Response<ImageResponse>
}

FakeDataDource

class FakeDataSource(private val list: MutableList<ShoppingItem> = mutableListOf()) : ShoppingDataSource {

    private val shoppingList  = MutableLiveData<List<ShoppingItem>>()
    get() {
        field.value=list
        return field
    }

    private val totalPrice = MutableLiveData<Float>()
    get(){
        var value=0f
        for(item in shoppingList.value!!){
            value+=(item.price*item.amount)
        }
        field.value=value
        return field
    }

    override suspend fun insertShoppingItem(shoppingItem: ShoppingItem) {
        list.add(shoppingItem)
    }

    override suspend fun deleteShoppingItem(shoppingItem: ShoppingItem) {
        list.remove(shoppingItem)
    }

    override fun getAllShoppingItems(): LiveData<List<ShoppingItem>> = shoppingList

    override fun getTotalPrice(): LiveData<Float> {
        return totalPrice
    }

    override suspend fun searchImage(q: String): Response<ImageResponse> {
        TODO("")
    }

I cannot use some booleans etc since it extends ShoppingDataSource Interface . I tried mocking as well but that didn't work . What should be done now?

0 Answers0