I'm new to Robolectric and instrumentation testing in general on Android. I followed along the guide for Robolectric for testing my first test. However I'm getting:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
I searched for the error, but no solution is helping. I'm including everything that could cause this error.
Gradle:
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt' //needed for source code generation
apply plugin: 'jacoco'
apply plugin: 'de.mobilej.unmock'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
testOptions {
unitTests.returnDefaultValues = true
}
defaultConfig {
applicationId "#######"
minSdkVersion 15
targetSdkVersion 22
testHandleProfiling true
testFunctionalTest true
versionCode 1
versionName "1.0"
}
buildTypes {
debug{
testCoverageEnabled false
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
jacoco {
version "0.7.1.201405082137"
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/dependencies.txt'
exclude 'META-INF/LGPL2.1'
exclude 'META-INF/services/javax.annotation.processing.Processor'
exclude 'LICENSE.txt'
}
jacoco {
version "0.7.1.201405082137"
}
}
def coverageSourceDirs = [
'../app/src/main/java'
]
unMock {
// URI to download the android-all.jar from. e.g. https://oss.sonatype.org/content/groups/public/org/robolectric/android-all/
allAndroid =
'https://oss.sonatype.org/content/groups/public/org/robolectric/android-all/4.3_r2-robolectric-0/android-all-4.3_r2-robolectric-0.jar'
// classes to keep
// matched by "startsWith" - you also need to include the dependencies manually
// if you start with an "-" the class will match by "equals" (and it will additionally match
// inner classes of this class)
keep = [
"android.view.LayoutInflater",
"android.support.v7.app.AppCompatActivity"
]
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:recyclerview-v7:22.0.+'
compile 'com.android.support:cardview-v7:22.0.+'
//Easy parsing JSON to POJO and vice versa
compile 'com.google.code.gson:gson:2.3.1'
//Photo's from URL to ImageView
compile 'com.squareup.picasso:picasso:2.5.2'
//REST API into an interface
compile 'com.squareup.retrofit:retrofit:1.9.0'
//Dependency Injection
compile 'com.google.dagger:dagger:2.0.1'
apt 'com.google.dagger:dagger-compiler:2.0.1'
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.jakewharton:butterknife:7.0.1'
//Realm
compile 'io.realm:realm-android:0.82.1'
//RxAndroid (old version)
compile 'io.reactivex:rxandroid:0.24.0'
testCompile 'org.mockito:mockito-core:1.10.19'
//Powermock
testCompile ('org.powermock:powermock-api-mockito:1.6.2'){
exclude group: 'org.mockito'
}
testCompile 'org.powermock:powermock-module-junit4:1.6.2'
//Testing Framework
//compile 'org.mockito:mockito-core:2.0.31-beta'
testCompile 'junit:junit:4.12'
//Robolectric
testCompile "org.robolectric:robolectric:2.4"
}
Manifest:
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".ui.MainActivity"
android:label="@string/title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
values/styles.xml
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- colorPrimary is used for the default action bar background -->
<item name="colorPrimary">@color/colorPrimary</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!-- colorAccent is used as the default value for colorControlActivated,
which is used to tint widgets -->
<item name="colorAccent">@color/accent</item>
<!-- set the application's background color -->
<item name="android:colorBackground">@color/icons</item>
</style>
MainActivity.java
public class MainActivity extends AppCompatActivity{
//implementation
}
MainActivityTest.java
@RunWith(RobolectricTestRunner.class)
public class MainActivityRoboTest {
@Test
public void test_onCreate_RecyclerViewShouldBeAvailable() throws Exception {
MainActivity activity = Robolectric.setupActivity(MainActivity.class);
RecyclerView r = (RecyclerView) activity.findViewById(R.id.rv);
}
}
Full Stacktrace
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
at android.support.v7.app.AppCompatDelegateImplBase.onCreate(AppCompatDelegateImplBase.java:124)
at android.support.v7.app.AppCompatDelegateImplV7.onCreate(AppCompatDelegateImplV7.java:146)
at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:59)
at ui.MainActivity.onCreate(MainActivity.java:38)
at android.app.Activity.performCreate(Activity.java:5008)
at org.robolectric.internal.ReflectionHelpers$3.run(ReflectionHelpers.java:64)
at org.robolectric.internal.ReflectionHelpers.traverseClassHierarchy(ReflectionHelpers.java:114)
at org.robolectric.internal.ReflectionHelpers.callInstanceMethodReflectively(ReflectionHelpers.java:59)
at org.robolectric.util.ActivityController$1.run(ActivityController.java:115)
at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:268)
at org.robolectric.util.ActivityController.create(ActivityController.java:111)
at org.robolectric.util.ActivityController.create(ActivityController.java:122)
at org.robolectric.util.ActivityController.setup(ActivityController.java:202)
at org.robolectric.Robolectric.setupActivity(Robolectric.java:1388)
at ui.MainActivityRoboTest.test_onCreate_RecyclerViewShouldBeAvailable(MainActivityRoboTest.java:21)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
I've just fixed same issue, and my workaround was this:
create a dummy Application and set theme inside onCreate():
public class TestApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
setTheme(R.style.AppTheme); //or just R.style.Theme_AppCompat
}
}
then inside the test you specify the application class in config:
@RunWith(RobolectricTestRunner.class)
@Config(application = TestApplication.class)
public class YourActivityTest {
//tests
}