1

I'm trying to test a Room database in Android, written in Kotlin, locally; that is not on an emulator and without instrumented testing. As I understand it this is possible using the Roboelectric framework but I'm having some trouble with this :

  • How does one select the appropriate class for the RunWith(CLASS) decorator ?

    I understand AndroidJUnit4 is necessary for instrumented tests, given that this is a local test should I be using JUnit4 instead or some other derivative from RoboElectric.

  • How should I correctly determine the context ?

    Trying InstrumentationRegistry.getTargetContext() requires that I use InstrumentationRegistry which isn't available when testing locally or that test can not be imported when importing androidx.test.platform.app.InstrumentationRegistry or android.support.test.InstrumentationRegistry. Trying ApplicationProvider.getApplicationContext() claims the reference getApplicationContext can't be found. I'm also not sure where I should be importing either InstrumentationRegistry or ApplicationProvider from.

In general I'm finding it tricky to determine the appropriate libraries to use in Java; all the documentation appears very version specific and assumes you magically know where to import a given class from where often such a classes appear in more then one library. Then package imported through gradle also seems to be well related but does not explicitly match the package being imported. If you have any general tips on this I would be quite keen to hear it.

My code so far is as follows:

package com.manaikan.airvendor.AirTime

import android.content.Context
import android.arch.persistence.room.Room
import androidx.test.platform.app.InstrumentationRegistry
import com.manaikan.airvendor.airtime.AirVendorDatabase
import com.manaikan.airvendor.airtime.BundleQuery
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import java.io.IOException
// Roboelectric
import androidx.test.core.app.ApplicationProvider

@RunWith(JUnit4::class)
class BundleTest {

    private lateinit var queryset : ENTITYDao
    private lateinit var database : APPLICATIONDatabase

    @Before
    fun setup()
    {
        val context = ApplicationProvider.getApplicationContext<Context>()
        database = Room.inMemoryDatabaseBuilder(context, APPLICATIONDatabase::class.java)
            .allowMainThreadQueries()
            .build()
        queryset = database.bundleQuery()
    }

    @After
    @Throws(IOException::class)
    fun tearDown()
    {
        database.close()
    }

    @Test
    @Throws(Exception::class)
    fun review()
    {
    }
}
1
  • Thanks for this start, this allowed me to locally test my Room implementation! Just a small comment, that may not even be real, your naming conventions seem strange, with these all uppercase names. We usually use CamelCase in java and kotlin ... Commented Nov 29, 2019 at 20:23

1 Answer 1

2

It seems to me you were almost there. The main thing to change is the runner, use: AndroidJUnit4, and maybe the version of the dependencies. Assuming your database and DAO are set up correctly, this should work (add import for your classes):

package com.manaikan.airvendor.AirTime

import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException

@RunWith(AndroidJUnit4::class)
class BundleTest {

  private lateinit var queryset : ChannelProgramsDao
  private lateinit var database : ChannelProgramsDatabase

  @Before
  fun setup()
  {
    val context = ApplicationProvider.getApplicationContext<Context>()
    database = Room.inMemoryDatabaseBuilder(context, APPLICATIONDatabase::class.java)
        .allowMainThreadQueries()
        .build()
    queryset = database.bundleQuery()
  }

  @After
  @Throws(IOException::class)
  fun tearDown()
  {
    database.close()
  }

  @Test
  @Throws(Exception::class)
  fun review()
  {
  }
}

It worked for me with the following dependencies:

  testImplementation "org.robolectric:robolectric:4.2"
  testImplementation "androidx.test.ext:junit:4.12"

  implementation "androidx.room:room-runtime:2.2.2"
  implementation "androidx.room:room-ktx:2.2.2"
  kapt "androidx.room:room-compiler:2.2.2"
  testImplementation "androidx.room:room-testing:2.2.2"
Sign up to request clarification or add additional context in comments.

1 Comment

I've marked this as the correct answer for now (I haven't looked into this is a while I'm afraid).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.