I've been running tests with Robolectric and it's all been great. Then I implemented Google Analytics to my application class and the tests started failing. The failing seems to occur when I inflate views during tests. Here's the stack trace:
java.lang.NullPointerException: null
at com.google.analytics.tracking.android.AnalyticsGmsCoreClient$AnalyticsServiceConnection.onServiceConnected(AnalyticsGmsCoreClient.java:176)
at org.robolectric.shadows.ShadowApplication$2.run(ShadowApplication.java:209)
at org.robolectric.util.Scheduler$PostedRunnable.run(Scheduler.java:162)
at org.robolectric.util.Scheduler.runOneTask(Scheduler.java:107)
at org.robolectric.util.Scheduler.advanceTo(Scheduler.java:92)
at org.robolectric.util.Scheduler.advanceToLastPostedRunnable(Scheduler.java:68)
at org.robolectric.util.Scheduler.unPause(Scheduler.java:25)
at org.robolectric.shadows.ShadowLooper.unPause(ShadowLooper.java:219)
at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:258)
at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:32)
at android.view.ViewGroup.addView(ViewGroup.java)
at android.view.ViewGroup.addView(ViewGroup.java:3225)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:750)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at org.robolectric.shadows.ShadowView.inflate(ShadowView.java:82)
at android.view.View.inflate(View.java)
Here's the Robolectric code for my BaseActivity:
#RunWith(RobolectricTestRunner.class)
public class BaseActivityTest {
ActivityController<TestActivity> activityController;
TestActivity activity;
#Before
public void setUp(){
activityController = Robolectric.buildActivity(TestActivity.class).create().start();
}
#After
public void takeDown(){
activityController.stop().destroy();
activity = null;
}
#Test
public void testOnPauseState(){
activity = activityController.resume().pause().get();
assertFalse(activity.getBus().isActive());
}
}
Following the Google Analytics example, my Application class implements Google Analytics. Whenever I run the tests with my Application, the break occurs. I've tried implementing Robolectric's MockApplication object, but that had no change; I had to remove Google Analytics from my Application object to have it work. Does anyone have any solutions that would allow me to run Robolectric with Google Analytics?
There is another solution if the previous posts don't work. Get a handle to the shadow application and configure it to ignore the analytics start intent binding. Do this in your test setup.
#Before
public void setup() {
ShadowApplication shadowApplication = Robolectric.shadowOf(Robolectric.application);
shadowApplication.declareActionUnbindable("com.google.android.gms.analytics.service.START");
}
I have two suggestions for you if you are using Google Analytics V3:
1) Have you tried calling this method when you run your tests?
googleAnalytics.setAppOptOut(true);
This will disable google analytics for the lifetime of the test.
2) Create a test application class in the same package as your current application and name it the same name but prepend "Test" to the name. This application will be created during your tests and you can set "setAppOptOut" set to true or you can omit GoogleAnalytics altogether from it.
More information can be found here: http://robolectric.blogspot.com/2013/04/the-test-lifecycle-in-20.html
I tried all the above solutions and none of them worked for me. This finally did:
public class TestFooApplication extends FooApplication {
#Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return false;
}
}
Related
Hello I have the following project structure
--App
|--SDK1
|--SDK2
In app I have some test for check SDK1 and SDK2.
In SDK I have a singleton pattern only to set the context by the application class that is in App.
And the context is set in the SDK1.singleton in the App.Application.onCreate
The problem is that when I try to execute the following code I always get null:
#RunWith(RobolectricTestRunner.class)
public class CallTest {
#Before
public void setUp() throws Exception {}
#Test
public void connectToSocketTest() {
if (BuildConfig.FLAVOR.equals("dev")) {
Context context = SDK1.getInstance().getContext();
assertNotNull(context);
...
Any idea why this happens, and how can solve it?
That's not the recommended way to get app context in Android using robolectric. You can get your activity by using below code...
Activity activity = Robolectric.setupActivity(MyActivity.class);
To get the app context, just call activity.getApplicationContext().
EDIT1: If you're using the latest Robolectric version, use
Robolectric.buildActivity(DashboardActivity.class) instead.
EDIT2: Make sure your SDK1 extends MultiDexApplication". Add this #Config(manifest=Config.NONE, application = App.class, sdk = 17)` to
the top of your test class.
Let me know if it works.
I run a specific unit-test:
#Rule
public ActivityScenarioRule<FragmentUtilActivity> activityScenarioRule2 =
new ActivityScenarioRule<>(FragmentUtilActivity.class);
#Before
public void setUp() {
... //not related to activityScenarioRule2
}
#Test
#Config(qualifiers = "sw600dp")
public void myTest() {
activityScenarioRule2
.getScenario()
.onActivity(
activity ->
standaloneAccountMenuDialogFragment.showNow(
activity.getSupportFragmentManager(), "FragmentTag"));
assertThat(...);
}
I see the #after code is called (with one breakpoint which turned into two breakpoints)
and I get this runtime error:
FragmentManager is already executing transactions
java.lang.IllegalStateException:
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManagerImpl.java:1551)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1611)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManagerImpl.java:137)
at android.os.Handler.handleCallback(Handler.java:790)
How can it be if I use activityScenario which is defined once and managed by #Rule annotation? It fails only for this specific test
Any ideas what can it be?
I have seen this issue with Robolectric and ActivityScenario, and it appears to be a race condition where the fragment isn't attached by the time we get to it. There's a warning about this in the default (LEGACY) LooperMode, which is what is used if a mode isn't specified. More details on that in the javadoc here
Try adding #LooperMode(LooperMode.Mode.PAUSED) to the top of your test class, which has some improvements on the Looper behavior. You may also need to add a shadowOf(getMainLooper()).idle() call in the teardown method.
Another workaround, if that doesn't help, is to add sdk=[27] to the config at the top of the test class like this-
#Config(sdk = [27])
There are more details on this issue - https://github.com/robolectric/robolectric/issues/3698
I'm using Evernotes android-job library for Scheduling jobs and everything works fine but, when i want to run a test case that is running with Robolecteric i get this error :
com.evernote.android.job.JobManagerCreateException: All APIs are disabled, cannot schedule any job
at com.evernote.android.job.JobManager.<init>(JobManager.java:184)
at com.evernote.android.job.JobManager.create(JobManager.java:107)
at com.M.MyApp.MyApplication.onCreate(MyApplication.java:63)
at org.robolectric.android.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:137)
at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:290)
at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:203)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109)
basically its pointing to line 63 of my application class :
JobManager.create(getApplicationContext()).addJobCreator(new JobMaker());
Just ran into this same issue after updating the Evernote library to 1.1.11
You can just wrap your initialisation of the JobManager in a try catch and swallow the exception, but a better solution is to create a test version of your application class and load that in for your tests.
The steps are described here.
Move line 63 of your application class to a method - called something like setUpJobManager() - and call that in your onCreate. Then override that method in the test version of your application class.
public class TestApplication extends AppController implements TestLifecycleApplication {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void createJobManager() {
}
Then pass the TestApplication class to your robolectric tests. Just make sure you correctly annotate your Robolectric test classes to use the test application class.
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 23, application = TestApplication.class)
I am working on implementing automated unit tests for our application. Want i need to do is be able to choose from a list of test cases and execute said test. My initial idea was to create (1) a standalone application that references a (2) testing library (android project with a bunch of unit tests) that would invoke the activities in our (3) application. So our application of course works fine and I don't want to make any changes there if possible. The standalone application would server as an interface to us developers for executing the tests. I want to be able to add more and more tests to the library. The issue I am having at this point is what follows.
In the library project I have a basic LoginTest activity.
public class LoginTest extends InstrumentationTestCase
{
... other class code
#Override
protected void setUp()
{
solo = new Solo(getInstrumentation());
}
}
My issue is the getInstrumentation() call always returns null. In my library manifest I have
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.matrix.edc.client.android" />
Make sure you have the robotium jar installed. The Solo class belongs to the robotium library.
If you have that installed and I've insulted your intelligence try changing your class declaration to
public class LoginTest extends ActivityInstrumentationTestCase2<YourMainActivity>
and change
solo = new Solo(getInstrumentation, getActivity());
in setUp().
You should also make sure, to call super.setUp() before any attempt of getting the instrumentation. I have not tested every subclass, but for ActivityInstrumentationTestCase2:
#Override
protected void setUp()
{
getInstrumentation(); // returns null
super.setUp()
getInstrumentation(); // returns valid instance
}
trying injecting the instrumentation in your setup, like so
public void setUp() throws Exception
{
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
solo = new Solo(getInstrumentation(), getActivity());
}
I have an android app that I am unit testing. I have 4 test classes each with multiple test methods. I run them all at the same time from a test suite. I ran into a problem on the emulator where the test would just freeze in the middle of running the tests. I switched to using an actual device and the problem went away.
Fast forward a few weeks and I'm not having the same problem while running tests on my device. I have been on Google for the last couple days trying to find a solution but nothing I have found has helped.
The Issue
When I try to run all the tests the test will freeze eventually. And by freeze I mean the test itself freezes. I saw one solution that it might be the phone or eclipse. I restarted my phone, updated everything in eclipse including eclipse itself. I tried changing views to see if maybe the eclipse view was not refreshing but none of that helped. I also tried using the junit v4 library instead of v3.
If I run the test methods individually they all run and pass. Its only when I run them all from the test suite that they fail.
The Log
I checked the log and this is what I get:
03-13 12:11:04.526: I/TestRunner(23175): started: testCheckShowDialogEnabled(com.package.name.MainActivityTest)
after that there is nothing else in the log.
On The Device
The app is finished and is removed from the screen. It it not reopened again at the beginning of the next test.
The Code
Here is the code that I think might be relevant. If you need any more code just let me know.
public class AllTests extends TestSuite {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(MainActivityTest.class);
suite.addTestSuite(DatabaseHandlerTest.class);
suite.addTestSuite(ClassOneTest.class);
suite.addTestSuite(AnotherActivityTest.class);
return suite;
}
}
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super("com.package.name", MainActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
mMainActivity = getActivity();
mSolo = new Solo(getInstrumentation(), mMainActivity);
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
mMainActivity = null;
}
// all the test methods
}
All my test classes implement setup() and tearDown() similarly.
Anyone out there know why my tests keep freezing? Any help or suggestions are greatly appreciated.
#smk pointed me in the direction to find a solution to this. I just changed my tearDown() to this:
#Override
protected void tearDown() throws Exception {
mSolo.finishOpenActivities();
super.tearDown();
}
Now it works great!