Sqlite Singleton causing issues with Robolectric - android

I have a project setup that is pretty standard, but I'm having issues using some of my unit tests. I have RxJava for observables as I run my unit tests, and I am seeing failures with my Sqlite DB integration.
My SQLiteHelper class runs as a singleton (getInstance()). When I run my projects using forkEvery = 1, causing a new JVM to spin up for each test, everything works fine. However, as soon as I stop doing that, I start getting errors with my tests because Sqlite is busy, or locked and I see errors like this
com.myproject.activities.ActivityTest > testButtonClicked FAILED
android.database.sqlite.SQLiteDatabaseLockedException at ActivityTest.java:477
Caused by: java.util.concurrent.ExecutionException at ActivityTest.java:477
Caused by: com.almworks.sqlite4java.SQLiteBusyException
It seems like none of the changes I make, other than running a single JVM at-a-time have any affect on this. Is there a better approach to fixing this?

Related

Shadow PackageParser.call ParsePackage PackageParser$Packageparserexception

I am trying to move my code to dynamic feature and while moving the test cases i created a test package inside dynamic feature module and moved related test classes there.
The test cases are not running and failing with below exception
java.lang.RuntimeException: android.content.pm.PackageParser$PackageParserException: Failed to parse /Users/anujjha/../build/intermediates/apk_for_local_test/debugUnitTest/packageDebugUnitTestForUnitTest/apk-for-local-test.ap_
at org.robolectric.shadows.ShadowPackageParser.callParsePackage(ShadowPackageParser.java:69)
at org.robolectric.android.internal.AndroidTestEnvironment.loadAppPackage_measured(AndroidTestEnvironment.java:314)
at org.robolectric.android.internal.AndroidTestEnvironment.lambda$loadAppPackage$1(AndroidTestEnvironment.java:284)
at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:53)
at org.robolectric.android.internal.AndroidTestEnvironment.loadAppPackage(AndroidTestEnvironment.java:282)
at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:178)
at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:169)
at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:301)
There are all junit test cases. Any idea how to make it work.and what can i check in code or gradle.

Re-run failed android tests

Is there a way to run only the failed set of tests on Android using Gradle?
At the moment, I run my tests as follows.
./gradle connectedDebugAndroidTest
There are tests that occasionally fail due to environment issues which are difficult to control and what I would like to do is be able to only run those failed tests and merge the result with the previous test results.
So for example, if I have 100 tests and 90 succeed, I would like to re-run the failing 10 tests. If those 10 pass the second time around, I would like to merge those results with the original test run.
It looks like this has been discussed several times for Gradle but there doesn't seem to be a solution yet.
https://github.com/gradle/gradle/issues/4068
https://github.com/gradle/gradle/issues/4450
https://github.com/gradle/gradle/issues/1283
Thanks!
The reason they don't have a way to only rerun failed tests is because it screws up the way Gradle currently works. This happens because on the first run, Gradle knows 90 tests passed. If you update the code, and then rerun only the 10 failed tests (using this new option you want them to add), then Gradle would think that all the tests have passed. However, this isn't the case because the tests which previously passed might've broken from the update which fixed the failing tests.
Despite this, the problem has been solved. Gradle reruns failed tests first, and provides a --fail-fast flag for the test task. This effectively does what you want (i.e., only reruns failed tests).
If you want to automatically rerun failed tests as part of the same build in which they failed, and succeed the build if they succeed on retry, you can use the Test Retry Gradle plugin. This will rerun each failed test a certain number of times, with the option of failing the build if too many failures have occurred overall.
plugins {
id 'org.gradle.test-retry' version '1.2.0'
}
test {
retry {
maxRetries = 3
maxFailures = 20 // Optional attribute
}
}

integrating react native into existing android app

So I have a pretty robust android application and I want to add some code from a react-native only application in one activity. I've gone through the docs on the site and it turned out to be a lot more complicated to integrate a react-native app into an existing android native app. Among the may errors, this is the one I'm current stuck on, does anyone know where this comes from?
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NoClassDefFoundError: com.facebook.react.CoreModulesPackage$1
at com.facebook.react.CoreModulesPackage.getNativeModules(CoreModulesPackage.java:96)
at com.facebook.react.LazyReactPackage.createNativeModules(LazyReactPackage.java:71)
at com.facebook.react.NativeModuleRegistryBuilder.processPackage(NativeModuleRegistryBuilder.java:97)
at com.facebook.react.ReactInstanceManager.processPackage(ReactInstanceManager.java:950)
at com.facebook.react.ReactInstanceManager.createReactContext(ReactInstanceManager.java:880)
at com.facebook.react.ReactInstanceManager.access$600(ReactInstanceManager.java:104)
at com.facebook.react.ReactInstanceManager$ReactContextInitAsyncTask.doInBackground(ReactInstanceManager.java:218)
at com.facebook.react.ReactInstanceManager$ReactContextInitAsyncTask.doInBackground(ReactInstanceManager.java:197)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818) 
It's currently fetching the bundle and it gets to 100 percent but then the activity crashes with the error output above about CoreModulesPackages.
It's been pretty frustrating trying to get this thing up and running, there seems to be a bunch of errors from many sides, I had to import react native manually through an aar since the version on maven is archaic(0.20), download okhttp web socket support, FLog and .so loader stuff. Among also having to exclude architecture specific code. If anyone knows of an easier way to integrate a RN app into an existing codebase, I'd really appreciate it.
I'm coming from the native side trying to understand this thing. I set up npm, bundle up the js before staring the server and then run my app. After which i forward to the proper 8081 port. If I'm doing the sequence of steps wrong then someone please correct me. It's been 3 days. Halp.
I encountered this same error in my react native app on Android 5.x devices -- no issues on 6 or 7.
The issue ceased to occur after I removed Fabric.io Crashlytics as a dependency from my app.
I got same error.
Probles has been solved by properly configuration of multidex for old android
In my case I forgot to inherit my application class from MultiDexApplication

SecurityProvider in Mockito Tests when run alongside Robolectric

We haven an Android project where we use MockitoTestRunner and RobolectricTestRunner for different kinds of tests.
I have written a set of unit test that are concerned with SSL, thus loading certs/keystores/truststores, etc. For this I used the MockitoJUnitRunner and added the Bouncycastle provider programmatically as such:
Security.insertProviderAt(new BouncyCastleProvider(), 1);
Now, these tests run perfectly fine when run on their own - e.g. when I directly run single methods from the test classes, or run these classes from the Project tree menu, they work just fine.
But when I run said tests along side ANY test which uses the RobolectricTestRunner (such as if I just run all the tests in my project together before committing), I get the following exception:
java.io.IOException: error constructing MAC:
java.lang.SecurityException: JCE cannot authenticate the provider BC
I'm baffled. How will the testrunner used in one test class affect the run of other classes, especially if we use a different test runner?
Additional info:
The exception only occurs once I actually try do do something with the BC provider (e.g. the first time the test tries to load a PKCS12 certificate) - the insertProviderAt(...) call itself seems to pass fine...
Also when I print out the list of providers for each test run, I see that Robolectric already has a BC provider in there, but is still failing when I try to use it.
Also if I don't add the BC provider, the tests still fail with the same error when run in a test suite alongside Robolectric tests. When run alone they fail with java.security.NoSuchProviderException: no such provider: BC, as we're specifying the provider explicitly.
Seems like Robolectric is using its own classloader (that favors its replacements on the Android API), which could be in conflicts with the regular classloader of Mockito.
So for using at the same time the Robolectric and mockito, you may do the following:
Make use of the Robolectric runner. Robolectric uses its own classloader that favors its replacements for the Android API, so it really does need to handle classloading on its own. There's no other way to use Robolecric.
Replace the #RunWith(MockitoJUnitRunner.class) with these alternative methods covering the behaviour of MockitoJUnitRunner:
#Before public void setUpMockito() {
MockitoAnnotations.initMocks(this);
}
#After public void tearDownMockito() {
Mockito.validateMockitoUsage();
}
Maybe it could be a workaround for using the Robolectric classloader and Mockito at the same time.

SQLiteException not an error at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)

I am facing an issue while running the junit test cases in android studio.
The issue is very strange as when I run the test cases for the first time in the phone it works perfectly fine, but if the app is already installed and when I run the test cases I get following error:-
net.sqlcipher.database.SQLiteException: not an error
at net.sqlcipher.database.SQLiteDatabase.dbopen(Native Method)
at net.sqlcipher.database.SQLiteDatabase.<init>(SQLiteDatabase.java:1942)
at net.sqlcipher.database.SQLiteDatabase.openDatabase(SQLiteDatabase.java:875)
at net.sqlcipher.database.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:907)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:132)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:99)
All the sqlcipher dependencies are correctly configured.
The database might not be properly closed after you run your app the first time. Try using Close method from SQLiteConnection class:
db.Close()
I found the solution for this issue.
When I saw in the logs, I found that the actual issue was
Unable to copy icudt46l.zip file
It was happening because i was not calling the loadlibs of SQLiteCipher inside the test suites.
So I added the following line in setup() method of my test class
SQLiteDatabase.loadLibs(getContext(), getContext().getFilesDir());

Categories

Resources