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)
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 .
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.
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.
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.
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.
Since Realm 0.87 you also need to include RxJava to your dependencies:
compile 'io.reactivex:rxjava:1.1.0'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With