Robolectric using Fragments and ActionBarCompat NullPointerException - java

I have an android application which uses fragments and has implemented ActionBarCompat. I wrote simple Robolectric test shown below:
#Test
public void shouldNotBeNull() throws Exception {
MainFragment mainFragment = new MainFragment();
startFragment(mainFragment);
assertThat(mainFragment, notNullValue());
assertThat(mainFragment.getActivity(), notNullValue());
}
private void startFragment(MainFragment fragment) {
FragmentActivity activity = new FragmentActivity();
shadowOf(activity).callOnCreate(null);
shadowOf(activity).callOnStart();
shadowOf(activity).callOnResume();
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(fragment, null);
fragmentTransaction.commit();
}
I am getting following exception:
java.lang.NullPointerException: null
at android.app.Activity.invalidateOptionsMenu(Activity.java:2595)
at android.support.v4.app.ActivityCompatHoneycomb.invalidateOptionsMenu(ActivityCompatHoneycomb.java:30)
at android.support.v4.app.FragmentActivity.supportInvalidateOptionsMenu(FragmentActivity.java:572)
at android.support.v4.app.Fragment.setHasOptionsMenu(Fragment.java:708)
at com.example.android.ui.MainFragment.onCreate(MainFragment.java:599)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:834)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:622)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)
at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:37)
at org.robolectric.shadows.ShadowLooper.post(ShadowLooper.java:198)
at org.robolectric.shadows.ShadowHandler.postDelayed(ShadowHandler.java:56)
at org.robolectric.shadows.ShadowHandler.post(ShadowHandler.java:51)
at android.os.Handler.post(Handler.java)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1322)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
at com.example.android.ui.MainFragmentTest.startFragment(MainFragmentTest.java:36)
at com.example.android.ui.MainFragmentTest.shouldNotBeNull(MainFragmentTest.java:22)
When using something like this:
MainActivity activity = new MainActivity();
shadowOf(activity).callOnCreate(null);
shadowOf(activity).callOnStart();
shadowOf(activity).callOnResume();
where MainActivity is holder activity for MainFragment, I get the following exception:
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at org.robolectric.res.builder.RobolectricPackageManager.getActivityInfo(RobolectricPackageManager.java:59)
at android.support.v7.app.ActionBarActivityDelegate.getUiOptionsFromMetadata(ActionBarActivityDelegate.java:157)
at android.support.v7.app.ActionBarActivityDelegateICS.onCreate(ActionBarActivityDelegateICS.java:53)
at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98)
at com.example.android.ui.MainActivity.onCreate(MainActivity.java:45)
at org.robolectric.shadows.ShadowActivity.invokeReflectively(ShadowActivity.java:176)
at org.robolectric.shadows.ShadowActivity.callOnCreate(ShadowActivity.java:121)
at com.example.android.ui.MainFragmentTest.startFragment(MainFragmentTest.java:28)
at com.example.android.ui.MainFragmentTest.shouldNotBeNull(MainFragmentTest.java:22)
I suspect it could be something about ActionBarCompat and Robolectric not being compatible. Any help would be appreciated.

As of Robolectric 2.4, it is supposed to support the Appcompat library. There are a few gotchas though as it doesn't work out of the box. Things that helped me:
Creating a project.properties file with the following contents
As described in the config manual:
target=android-19 android.library.reference.1=/../../build/intermediates/exploded-aar/com.android.support/appcompat-v7/20.0.0
android.library.reference.2=/../../build/intermediates/exploded-aar/com.android.support/support-v4/20.0.0
android.library.reference.3=/../../build/intermediates/exploded-aar/com.viewpagerindicator/library/2.4.1
Setting exculdes in build.gradle for Robolectric
Apparently Robolectric has its own versions of the support libraries so the following is needed to prevent possible duplicate dependencies (referenced from here):
androidTestCompile('org.robolectric:robolectric:2.4') {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'appcompat-v7' }

Related

Duplicate class found i module

Duplicate class org.apache.http.impl.client.CloseableHttpClient found in modules jetified-ipp-v3-java-devkit-5.0-jar-with-dependencies.2-jar-with-dependencies
(com.intuit.quickbooks-online:ipp-v3-java-devkit:5.0.2) and
jetified-oauth2-platform-api-5.0-jar-with-dependencies.2-jar-with-dependencies
(com.intuit.quickbooks-online:oauth2-platform-api:5.0.2)
Getting above error
I have tried
1.configurations {
runtime.exclude group: 'com.intuit.quickbooks-online', module: 'ipp-v3-java-devkit'
}
2. configurations {
implementation.exclude group: 'com.intuit.quickbooks-online', module: 'ipp-v3-java-devkit'
}
but no luck till yet

Duplicate class org.apache.commons

I am trying to run a build on Android. I'm in the process of building a React-Native bridge for a Java library. However, I am getting a Duplicate class error which looks like follows:
Duplicate class org.apache.commons.lang3.builder.CompareToBuilder
found in modules commons-lang3-3.9.jar (org.apache.commons:commons-lang3:3.9)
and creditCardNfcReader-1.0.3-runtime.jar (com.github.pro100svitlo:creditCardNfcReader:1.0.3)
There are an entire list of these errors being printed out. There is also a slightly different error which looks like this:
Duplicate class bolts.BoltsExecutors$ImmediateExecutor found in
modules bolts-tasks-1.4.0.jar (com.parse.bolts:bolts-tasks:1.4.0)
and jetified-bolts-android-1.1.2.jar (com.parse.bolts:bolts-android:1.1.2)
My dependencies currently look like this in my build.gradle file:
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+"
implementation 'com.github.pro100svitlo:creditCardNfcReader:1.0.3'
addUnimodulesDependencies()
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
I have tried to exclude modules and groups from the dependencies with no luck yet. Here are a few approaches I have tried as recommended from several sources:
1.
implementation ("com.facebook.react:react-native:+") {
exclude group: 'com.parse.bolts', module: 'bolts-tasks'
}
2.
implementation ("com.facebook.react:react-native:+") { exclude module: 'bolts-tasks'}
3.
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+"
implementation 'com.github.pro100svitlo:creditCardNfcReader:1.0.3'
addUnimodulesDependencies()
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
configurations { runtime.exclude group: '*' }
I would really appreciate any help with finding a solution to this problem. Thanks in advance.
The exclude method of the configuration closure for a dependency excludes transitive dependencies. So, if your module dependency depends on other modules, you can exclude them from your build. You can check out the transitive dependencies of the 'com.facebook.react:react-native:+' module on its maven repo.
https://mvnrepository.com/artifact/com.facebook.react/react-native/0.20.1
Try specify the version of dependency instead of use '+' to avoid conflict.
Here is some reference to check on resolving the plugins and dependency jar conflicts.
jarjar package reference

Class did not get auto generated

I am learning how to use Dagger2. I created an example as shown below in the code. the issue I am facing is, the auto generated class by Daggers, the one
that should be called "DaggerInterfaceComponent" is never gets created. The below DaggerInterfaceComponent is underscored with red.
Please have a look at the build gradle App posted below.
code:
InterfaceComponent component = DaggerInterfaceComponent.builder().objectValuesModule(new ObjectValuesModule()).build();
Object injectedObject = component.getObjectValues();
int returnedInt = injectedObject.getreturnInteger();
int returnedStr = injectedObject.getReturnString();
int returnedObj = injectedObject.getReturnObject();
gradle App
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-
core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile "com.google.dagger:dagger:2.11"
annotationProcessor "com.google.dagger:dagger-compiler:2.11"
provided 'javax.annotation:jsr250-api:1.0'
compile 'javax.inject:javax.inject:1'
}

Setting up Roboelectric testing for android

I am trying to add some Roboelectric unit tests to my app.
Using Roboelectric 3.0 i want to be able to test my activity PinActivity and the fragment that is in it.
import android.support.v7.app.AppCompatActivity;
import android.app.Fragment;
PinActivity extends AppCompatActivity {
gradle file contains:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:robolectric:3.0"
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
}
PinActivityTest contains: (Edited to add #Config did not fix)
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import static org.junit.Assert.*;
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
public class PinActivityTest {
#Test
public void onCreate_shouldInflateLayout() throws Exception {
PinActivity activity = Robolectric.buildActivity(PinActivity.class).create().get();
assertNotNull(activity);
}
Currently getting:
WARNING: No manifest file found at .\AndroidManifest.xml.Falling back to the Android OS resources only. To remove this warning, annotate your test class with #Config(manifest=Config.NONE). and java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
Why can't it find my AndroidManifest?
Anyone know how i can fix this or more Roboelectric tutorials with similar examples?
As log says, you forgot about #Config annotation, so it could not find your AndroidManifest file:
Try this:
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21) public class PinActivityTest {
#Test
public void onCreate_shouldInflateLayout() throws Exception {
PinActivity activity = Robolectric.buildActivity(PinActivity.class).create().get();
assertNotNull(activity);
}
As Roboelectric not support already API23, I set up test sdk as API 21.
EDIT: Change also:
PinActivity activity = Robolectric.buildActivity(PinActivity.class).create().get()
to
PinActivity activity = Robolectric.setupActivity(PinActivity.class);
NOTE: My Robolectric dependencies looks now:
testCompile("org.robolectric:robolectric:3.0") {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
}
If you have any question, please free to ask.
Hope it help

AndroidStudio Robolectric Unit Tests - Invaild default

I want to use Unit Testsfor my Android Application. First, I've tried the Unit-Tests with Robolectric with a template Project "deckard-gradle-master". As it worked fine, I wanted to integrate this testing in my existing Android Application.
I have added the libraries hamcrest-core-1.3.jar, junit-4.12.jar, robolectric-2.4.jar and robolectric-gradle-plugin-1.0.1.jar.
When i try to start my TestClass in this Project, I always get the following Exception:
Exception in thread "main" java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class org.robolectric.annotation.Config.application()
at java.lang.reflect.Method.getDefaultValue(Method.java:611)
at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:128)
at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:266)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
at java.lang.Class.createAnnotationData(Class.java:3521)
at java.lang.Class.annotationData(Class.java:3510)
at java.lang.Class.getAnnotation(Class.java:3415)
at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:199)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:39)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
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:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Process finished with exit code 1
I really don't know what to do anymore, but i think something is missing. Unfortunately i don't know what.
These are my gradle-files:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
and
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.bieren.myapplication"
minSdkVersion 19
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:21.0.3'
compile files('libs/junit-4.12.jar')
compile files('libs/robolectric-2.4.jar')
compile files('libs/robolectric-annotations-2.4.jar')
compile files('libs/hamcrest-core-1.3.jar')
compile files('libs/android.jar')
compile files('libs/android-libcore-4.3_r2.robolectric-0.jar')
compile files('libs/robolectric-2.4-jar-with-dependencies.jar')
compile files('libs/android-support-v4.jar')
compile files('libs/maps.jar')
androidTestCompile 'org.hamcrest:hamcrest-integration:1.1'
androidTestCompile 'org.hamcrest:hamcrest-core:1.1'
androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
androidTestCompile('junit:junit:4.+') {
exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.3') {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'support-v4'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
}
compile files('libs/robolectric-gradle-plugin-1.0.1.jar')
}
This is my Testclass:
package com.example.bieren.testapplication.test;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
#RunWith(RobolectricTestRunner.class)
#Config(manifest = "src/main/AndroidManifest.xml", emulateSdk = 18)
public class MainActivityTest {
private MainActivity activity;
#Test
public void testIcon() throws Exception {
String play_icon = new MainActivity().getResources().getString(R.string.icon_play);
assertThat(play_icon, equalTo(""));
}
#Before
public void setup(){
this.activity = Robolectric.buildActivity(MainActivity.class).create().get();
}
#Test
public void buttonClickShouldSetText() throws Exception
{
Button button = (Button) activity.findViewById(R.id.button);
TextView textView = (TextView) activity.findViewById(R.id.nachricht);
textView.setText("Hans Hans");
button.performClick();
assertEquals(textView.getText(),"Hans Hans");
}
}
I would really be more than thankful if someone could tell me whats the problem and what's missing.
Timon
Deleting the .gradle folder works for me every time!
If you do not find the .gradle folder, this might be hidden. In that case, go to your project directory and run the following command to remove the .gradle folder.
rm -rf .gradle/
Changing the #Config to
#Config(manifest = "app/src/main/AndroidManifest.xml", emulateSdk = 18, reportSdk = 18)
solved the problem for me.
If you use the new testing environment, configuring Robolectric is more seamless. Look at this link in order to set up your project with the new testing environment.
Just as a heads up, you will need to upgrade Android Studio to 1.1 RC1 or greater for this to work.
This approach avoids having to use any kind of plugin for Robolectric.

Categories

Resources