How to hide or exclude sqlcipher from robolectric?


#1

We were working on building a significant new feature for our app.

To speed development, we tried to build the feature independently of our app, and then bring it over.

Worked for iOS, not so much for Android.

Current issue is that the test suite is written using Robolectric for speed of running the tests…however, now that we’re trying to run the tests in the full app, we realise that we didn’t use sqlcipher in the independent build.

So, when I try to run a test case now, I get this error:
java.lang.UnsatisfiedLinkError: no sqlcipher in java.library.path

at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:181)
at net.sqlcipher.database.SQLiteDatabase.loadLibs(SQLiteDatabase.java:174)
at com.crowdlab.CLDatabase.initialiseDatabase(CLDatabase.java:79)
at com.crowdlab.CLDatabase.initialise(CLDatabase.java:60)
at com.crowdlab.BaseApplication.onCreate(BaseApplication.java:61)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:165)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:423)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:254)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:191)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:56)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:157)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Fair enough. Is there a way to get sqlcipher to play nicely with Robolectric (such as shadows, maybe), or to tell Robolectric to ignore sqlcipher?


#2

Hello @kcorey

Unfortunately SQLCipher for Android does not interoperate with Robolectric well because Robolectic runs on the desktop JVM, SQLCipher for Android includes native libraries built to target different Android CPU architectures. Two possible approaches to consider:

  1. Utilize mocks at runtime for tests that interface with a data layer. The drawback here is that you cannot actually test the various SQL commands you might execute within the running application.
  2. Consider an analagous approach which is used within the SQLCipher for Android test suite. In this case, a test runner executes tests on device/emulator. The pro here is the ability to execute the same queries against a real database on different device(s)/emulator(s). The drawback is speed; which is no way near as fast as typical JUnit style tests.

#3

Thanks for the quick answer…but…ouch!

For the record, saw a post for another approach, where you use two different OpenHelpers, one for secure and one for not secure:

Hrm…going through the options:

For your #1, I’d need to rewrite (or at least check) the interfaces on 1000+ classes to change how we use the database.

For your #2, I’d have slower tests, which is kinda the problem we were hoping to solve.

For the link above, I’d need to revisit the 1000+ classes again…

Or finally just rewrite tests for 20 classes to not use Robolectric.

Guess I’m rewriting tests. :slight_smile:

Thanks,

-Ken