Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm Unit Test on Android

Trying to unit test a class that does some calls to Realm (0.87.4), the test setup fails with

java.lang.NoClassDefFoundError: rx/Observable$OnSubscribe
at io.realm.RealmConfiguration$Builder.<init>(RealmConfiguration.java:279)
at org.testapp.db.MyClassTest.setUp(MyClassTest.java:34)
... 
Caused by: java.lang.ClassNotFoundException: rx.Observable$OnSubscribe
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)

My test class starts with:

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest extends TestCase {

@Rule
public TemporaryFolder testFolder = new TemporaryFolder();

Realm realm;

@Before
public void setUp() throws Exception {
    File tempFolder = testFolder.newFolder("realmdata");
    RealmConfiguration config = new RealmConfiguration.Builder(tempFolder).build();

    realm = Realm.getInstance(config);
}
...

My gradle has:

testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:1.10.19"
testCompile "org.robolectric:robolectric:3.0"
compile 'io.realm:realm-android:0.87.4'

How to solve this?

=== EDIT 1 ===

I added to my gradle:

testCompile 'io.reactivex:rxjava:1.1.0'

and

android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}

the new error is

java.lang.UnsatisfiedLinkError: no realm-jni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at io.realm.internal.RealmCore.loadLibrary(RealmCore.java:117)
like image 879
Frank Avatar asked Feb 02 '16 12:02

Frank


People also ask

How do I run unit test on Android?

To run all tests in a class or a specific method, open the test file in the Code Editor and do either of the following: Press the Run test icon in the gutter. Right-click on the test class or method and click Run . Select the test class or method and use shortcut Control+Shift+R .

What is unit testing in Android app?

Unit tests or small tests only verify a very small portion of the app, such as a method or class. End-to-end tests or big tests verify larger parts of the app at the same time, such as a whole screen or user flow. Medium tests are in between and check the integration between two or more units.

Which Java framework is used to write unit tests in Android?

2. JUnit. JUnit is an open-source foundation of testing frameworks on the Java Virtual Machine. The aim of the JUnit testing framework primarily focuses on efficiently creating and executing unit testing for an application.

Why is Singleton not testable?

It's very difficult to write unit tests for code that uses singletons because it is generally tightly coupled with the singleton instance, which makes it hard to control the creation of singleton or mock it.


2 Answers

Unit tests are hard or impossible when using Realm in the class that you are testing (thanks Dmitry for mentioning). What I can do is run the tests as instrumental tests (thanks Dmitry, Christian).

And that is quite easy, I won't have to change anything to the test methods...

A. Move the test class into an "androidTest" folder, instead of "test". (Since Android Studio 1.1 you should put your Unit tests in /src/test and Android Instrumentation Tests in /src/androidTest)

B. Add the dependencies for instrumental tests in the gradle build file, use "androidTest" because they're instrumental:

androidTestCompile 'junit:junit:4.12'
androidTestCompile 'io.reactivex:rxjava:1.1.0'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support:support-annotations:23.1.1'

C. In the test class, replace the runner at the top with AndroidJUnit4:

@RunWith(AndroidJUnit4.class)
public class MyClassTest extends TestCase {
...

Create an Android run configuration of type "Android Tests", run it and voila, it will test the same methods fine now, but on a device. Makes me very happy.

like image 189
Frank Avatar answered Oct 19 '22 02:10

Frank


Since Realm 0.87 you also need to include RxJava to your dependencies:

compile 'io.reactivex:rxjava:1.1.0'
like image 41
Dmitry Zaytsev Avatar answered Oct 19 '22 01:10

Dmitry Zaytsev