Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock Room database for Unit tests

I'm trying to make some Unit tests for my business logic.

Data is read and written to Room database, so the logic depends on what's inside my database.

I can easily buildInMemoryDatabase and test all the logic, but using Instrumental tests which are slow and require a device to be connected.

I want to run Unit tests only where I replace my RoomRepository with some other implementation of Repository interface

class RoomRepository(
    private val database: RoomDatabase //actual room database
): Repository {

    override fun getFooByType(type: Int): Maybe<List<Item>> {
        return database.fooDao()
            .getFooByType(type)
            .map { names ->
                names.map { name -> Item(name) }
            }
            .subscribeOn(Schedulers.io())
    }
}

Maybe there is a way to run Room sqlite on host machine?

Maybe there is another solution?

like image 375
nutella_eater Avatar asked Jan 22 '19 15:01

nutella_eater


1 Answers

Create a wrapper class named "Repository" around the RoomDatabase and have methods to expose the Dao objects. By that way, we can easily mock the repository class like below

Open class Repository(private val roomDatabase:RoomDatabase){

  open fun productsDao():ProductsDao = roomDatabase.productDao()
  open fun clientsDao():ClientsDao = roomDatabase.clientsDao()

  //additional repository logic here if you want

}

Now, in tests, this class can be easily mocked like

val repositoryMock = mock(Repository::class.java)
val productsDaoMock = mock(ProductsDao::class.java)

when(repositoryMock.productsDao()).thenReturn(productsDaoMock)
when(productsDaoMock.getProducts()).thenReturn(listof("ball","pen")

So, inject and use the repository class instead of RoomDatabase class in all the places of your project so that the repository and all the Dao can be easily mocked

like image 132
Sundaravel Avatar answered Oct 05 '22 02:10

Sundaravel