SecurityProvider in Mockito Tests when run alongside Robolectric - android

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.

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.

Sqlite Singleton causing issues with Robolectric

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?

Mocking Google Analytics v4

I'm trying to test my code that depends on Google Analytics SDK v4.
Specifically I'm trying to mock com.google.android.gms.analytics.Tracker with Mockito.
Tracker tracker = Mockito.mock(Tracker.class); yields this error.
Are there any approaches to take? The only thing I can think of is to create my own wrapper.
I believe the code snipped at fault is Tracker.class - as this will instantiate the class, which in turn throws the VerifyError. This is not an issue with your code, but is a limitation of Google Play Services. The issue has been reported in the Robolectric project and here.
I used the solution provided in the second link by SuperJugy, by inserting the following to the bottom of my Gradle build file:
tasks.withType(Test) {
test {
// set JVM arguments for the test JVM(s)
jvmArgs '-XX:-UseSplitVerifier'
}
}
To get it working in Android Studio I had to add the VM Option -noverify to my test build configuration.
I think you may be able to work-around the problem using a wrapper, so long as the wrapper code never instantiates the Tracker class. However this may not be easy (or possible?), please let me know if end up going down this path and succeed!

Android BluetoothAdapter Mocking

I'm trying to mock test Bluetooth application but my first step of creating a mock object of BluetoothAdapter class is not working!!
I'm using powermockito with easy mock.
mBluetoothAdapter = (BluetoothAdapter)PowerMock.createMock(BluetoothAdapter.class);
this fails. with the following stack trace
java.lang.IllegalArgumentException: No visible constructors in class android.bluetooth.BluetoothAdapter
at org.easymock.internal.DefaultClassInstantiator.getConstructorToUse(DefaultClassInstantiator.java:94)
at org.easymock.internal.AndroidClassProxyFactory.createProxy(AndroidClassProxyFactory.java:48)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:114)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:88)
at org.easymock.internal.MocksControl.createMock(MocksControl.java:79)
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2212)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
at org.powermock.api.easymock.PowerMock.createMock(PowerMock.java:89)
at com.xxx.blesimplesample.test.MainActivityTest.setUp(MainActivityTest.java:59)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1710)
Any one has used any mocking framework for Bluetooth app mocking? Any suggestions will be v helpful
BluetoothAdapter in the Android framework is declared final, so at the time you asked this question, it couldn't be mocked, neither with Mockito nor using Robolectric.
However, Android unit testing has changed a lot since then. With recent versions of the tools, when you build unit tests the tools generate a patched android.jar with all the finals removed. This makes all Android classes available for mocking. Nowadays, if you want to mock any Bluetooth code, you can do so in the standard way. The code you've already tried will "just work" if you update to the latest tools. Alternatively, Robolectric has a ShadowBluetoothAdapter class built in now.

infinitest usage with Robotium for Android

I cant get infinitest(continuous test runner for TDD) to auto test with android junit test cases. Im using Robotium for UI testing.
Is infinitest compatible with Robotium ?
Here is the Problem page error (within eclipse Problem window) i get even though my test cases run fine when executed manually:
Description Resource Path Location Type
RuntimeException (Stub!) in ProjectTests. ProjectTests.java
line 0 Infinitest Test Failure

Categories

Resources