Robolectric and Evernotes android-job library - android

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)

Related

Robolectric dosen't calling Application.onCreate(), and I cannot get context

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.

Tell Espresso to run specific tests on an emulator

I have Android instrumentation tests with Espresso. Some of my tests must be run on an emulator - due to using LinkedIn's TestButler (https://github.com/linkedin/test-butler) library. This library toggles wifi/gsm for specific test runs, and that is why these tests must be run on an emulator.
My question is - can I annotate any specific tests to run on an emulator, while having the other tests run on a real device?
Thanks
Yes, you can use a #ConditionalIgnore annotation as described in http://www.codeaffine.com/2013/11/18/a-junit-rule-to-conditionally-ignore-tests/.
You will have something like
public class SomeTest {
#Rule
public ConditionalIgnoreRule rule = new ConditionalIgnoreRule();
#Test
#ConditionalIgnore( condition = NotRunningOnEmulator.class )
public void testSomething() {
// ...
}
}
public class NotRunningOnEmulator implements IgnoreCondition {
public boolean isSatisfied() {
return !Build.PRODUCT.startsWith("sdk_google");
}
}
EDIT
For this specific case of detecting a device or emulator you can also use #RequiresDevice.
The most straightforward solution I found is to use JUnit Assume API: http://junit.org/junit4/javadoc/4.12/org/junit/Assume.html
So, inside the test methods that can only be run on an emulator, I put this code:
Assume.assumeTrue("This test must be run in an emulator!", Build.PRODUCT.startsWith("sdk_google"));
This results in the said test being ignored when it isn't run on an emulator, and a handy error msg in the run window:
As you can see, the other two tests passed fine (in the green), and the entire test suite was able to run.

Can you call getInstrumentation() from a test class in a referenced Android library?

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());
}

Robolectric and Google Analytics Error on Tests

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;
}
}

Problems with running Android Activity unit-testing from Eclipse

Im having a problem starting or running any activity unit tests from within eclipse.
Even i start a clean project and make a simple test class it always prints to the console:
[2010-10-05 13:10:24 - testAndroid] Collecting test information
[2010-10-05 13:10:25 - testAndroid] Test run failed: Test run incomplete. Expected 2 tests, received 0
Any ideas ?
Just for testing, I have created a fresh Android project called Demo with a test project called DemoTest
The main activity to test is called Main and I have created a simple testclass MainTest that looks like this:
package net.demo.test;
import android.test.ActivityInstrumentationTestCase2;
import net.demo.Main;
public class MainTest extends ActivityInstrumentationTestCase2<Main>
{
public MainTest()
{
super("net.demo", Main.class);
// TODO Auto-generated constructor stub
}
}
My tests used to run fine before, but suddenly I cant run any of them, they all fail with the same error, even I create new a project. It seems like it something to do with Eclipse or and not with the Code.
Update:
Seems like extending SingleLaunchActivityTestCase<Main> is working, but still got no clue about how to make ActivityInstrumentationTestCase2<Main> working.
I had no regression problems. I just couldn't get the example to work. I finally fixed it by defining two constructors:
public MainActivityTest(String pkg, Class<MainActivity> activityClass) {
super("com.myapp", MainActivity.class);
}
public MainActivityTest() {
super("com.myapp", MainActivity.class);
}
It turned out that most emulators before 2.3.3 were silently swallowing the error generated when construction went wrong.
You must put at least 2 methods (i.e 2 test cases) into the Test class. even methods without definition inside can do the trick

Categories

Resources