Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm access from incorrect thread in Espresso

Before each espresso test, I have an annotation @Before where I initialize my RealmManager.realm.

Code snippet of my object Realm:

init {
    Realm.init(SaiApplication.context)
    val builder = RealmConfiguration.Builder().schemaVersion(SCHEMA_VERSION)
    builder.migration(runMigrations())
    if (!BuildConfig.DEBUG) builder.encryptionKey(getOrCreateDatabaseKey())
    if (SaiApplication.inMemoryDatabase) builder.inMemory()
    Realm.setDefaultConfiguration(builder.build())
    try {
        errorOccurred = false
        realm = Realm.getDefaultInstance()
    } catch (e: Exception) {
        errorOccurred = true
        realm = Realm.getInstance(RealmConfiguration.Builder()
                .schemaVersion(SCHEMA_VERSION).name(errorDbName).build())
        e.log()
        deleteRealmFile(realm.configuration.realmDirectory)
    }
}

But when I run my tests, I get next error:

Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created

So how i can correctly init my realm in my tests?

One of the solutions that I found interesting, create a fake init realm.

like image 697
Morozov Avatar asked Jun 12 '17 08:06

Morozov


2 Answers

To manipulate the UI thread's Realm instance from your UI tests, you need to initialize the Realm instance on the UI thread using instrumentation.runOnMainSync(() -> {...});.

@Before
public void setup() {
    Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
    instrumentation.runOnMainSync(new Runnable() {
        @Override
        public void run() {
           // setup UI thread Realm instance configuration
        }
    });
}
like image 85
EpicPandaForce Avatar answered Nov 03 '22 03:11

EpicPandaForce


What i do. I just added next function in my AppTools, which check package with tests:

fun isTestsSuite() = AppResources.appContext?.classLoader.toString().contains("tests")

Then modifed init of Realm:

 init {
    Realm.init(AppResources.appContext)
    val builder = RealmConfiguration.Builder().schemaVersion(SCHEMA_VERSION)
    builder.migration(runMigrations())
    if (!isTestsSuite()) builder.encryptionKey(getOrCreateDatabaseKey()) else builder.inMemory()
    Realm.setDefaultConfiguration(builder.build())
    try {
        errorOccurred = false
        realm = Realm.getDefaultInstance()
    } catch (e: Exception) {
        errorOccurred = true
        realm = Realm.getInstance(RealmConfiguration.Builder()
                .schemaVersion(SCHEMA_VERSION).name(errorDbName).build())
        e.log()
        deleteRealmFile(realm.configuration.realmDirectory)
    }
}
like image 31
Morozov Avatar answered Nov 03 '22 02:11

Morozov