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.
Related
Gradle v7.3.3
I'm trying to use the The Java Platform Plugin, and I have this so far in my platform build.gradle file
artifactId = "my-java-platform"
group = "com.mycompany.platform"
version = "1.0.0"
dependencies {
constraints {
...
api "org.slf4j:slf4j-log4j12:1.7.9"
api "org.projectlombok:lombok:1.16.18"
...
}
}
I did a ./gradlew publishToMavenLocal and see the resulting pom.xml file with those 2 dependencies.
Then in my application's build.gradle file I have
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
compileOnly group: "org.slf4j", name: "slf4j-log4j12"
compileOnly group: "org.projectlombok", name: "lombok"
...
}
One of my applications source code has
package com.mycompany.common
import java.util.TimeZone;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class ObjectMapperConfiguration {
private static ObjectMapper objectMapper;
/**
* Static only
*/
private ObjectMapperConfiguration() {}
/**
* Work with Spring to configure the ObjectMapper
*/
public static ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
objectMapper = builder.createXmlMapper(false).build();
configureObjectMapper(objectMapper);
log.info("The ObjectMapperConfiguration has run");
return objectMapper;
}
...
}
But I get
$ ./gradlew clean build
> Task :compileJava FAILED
/Users/.../src/main/java/com/company/common/ObjectMapperConfiguration.java:39: error: cannot find symbol
log.info("The ObjectMapperConfiguration has run");
^
symbol: variable log
location: class com.company.common.ObjectMapperConfiguration
I understand that the log variable is defined in the #Slf4j annotation? If so why am I getting the error? Thanks!
The Lombok magic is implemented via an annotation processor.
See here for the recommended Lombok Gradle config
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testCompileOnly 'org.projectlombok:lombok:1.18.22'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
}
The application's build.gradle file, the one that uses the platform, should look like this
dependencies {
implementation platform(group: "com.mycompany.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor platform(group: "com.company.platform", name: "my-java-platform", version: "1.0.0")
annotationProcessor group: "org.projectlombok", name: "lombok"
...
}
Currently, I'm getting Unresolved reference: spek and Unresolved reference: test with testCompile / testRuntime:
project(":core") {
apply plugin: "kotlin"
dependencies {
// ... other dependencies
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion"
testCompile "org.jetbrains.spek:spek-api:$spekVersion"
testRuntime "org.jetbrains.spek:spek-junit-platform-engine:$spekVersion"
testCompile "com.nhaarman:mockito-kotlin:$mockitoVersion"
testCompile "com.natpryce:hamkrest:$hamkrestVersion"
}
}
However, when I switch them with compile / runtime, I can run the tests successfully!
Here's my spek test:
package com.mysampleapp
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.describe
import org.jetbrains.spek.api.dsl.it
import kotlin.test.assertEquals
class DummySpec : Spek({
describe("a dummy") {
it("contains a number") {
val dummy = Dummy(1)
assertEquals(1, dummy.number)
}
}
})
Could someone please help me to debug this?
Thank you
I found out the cause. My tests are inside my Source Folder.
To fix this, I moved my tests out, so Source Folder will not overlap with Tests Source Folder.
tried to follow this and this but without any luck.
I am using Android studio 3.0 and junit 4.12. Windows 10.
What I have tried:
move the junit dependency up (tried test compilation and implementation scope)
delete the tests in Run - Edit configurations... - remove all under Android JUnit and Android App
My graddle looks like this:
apply plugin: 'kotlin'
dependencies {
implementation project(':domain')
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompileOnly 'junit:junit:4.12'
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'io.reactivex.rxjava2:rxkotlin:2.1.0'
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testImplementation 'com.nhaarman:mockito-kotlin:1.1.0'
testImplementation 'org.amshove.kluent:kluent:1.14'
implementation 'com.google.api.client:google-api-client-repackaged-com-google-common-base:1.2.3-alpha'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
}
My test looks like this:
package ***.roompanel.data;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.TypeAdapterFactory;
import ***.roompanel.data.RestApi.ApiFieldNamingStrategy;
import ***.roompanel.data.RestApi.ApiGsonBuilder;
import ***.roompanel.data.RestApi.ApiItemTypeAdapterFactory;
import ***.roompanel.data.RestApi.ApiService;
import ***.roompanel.data.RestApi.IApiService;
import ***.roompanel.data.repository.EventRepository;
import ***.roompanel.domain.model.event.Event;
import ***.roompanel.domain.repository.IEventRepository;
import org.junit.Before;
import org.junit.Test;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class EventRepositoryTest {
IEventRepository repo;
#Before
public void setUp() {
TypeAdapterFactory typeAdatperFactory = new ApiItemTypeAdapterFactory(); // system to
FieldNamingStrategy fieldNamingStrategy = new ApiFieldNamingStrategy();
Gson gson = new ApiGsonBuilder(typeAdatperFactory, fieldNamingStrategy).build();
IApiService service = new ApiService(gson);
this.repo = new EventRepository(service);
}
#Test
public void events_void_success() throws Exception {
Date start = new Date(2017,10,01);
Date end = new Date(2017,10,12);
List<Event> events = (List<Event>) repo.load(start, end);
assertNotNull(events);
}
}
UPDATE:
./gradlew test
BUILD SUCCESSFUL in 25s
53 actionable tasks: 30 executed, 23 up-to-date
Stacktrace:
java.lang.RuntimeException: Stub!
at junit.runner.BaseTestRunner.<init>(BaseTestRunner.java:5)
at junit.textui.TestRunner.<init>(TestRunner.java:54)
at junit.textui.TestRunner.<init>(TestRunner.java:48)
at junit.textui.TestRunner.<init>(TestRunner.java:41)
at com.intellij.rt.execution.junit.JUnitStarter.junitVersionChecks(JUnitStarter.java:224)
at com.intellij.rt.execution.junit.JUnitStarter.canWorkWithJUnitVersion(JUnitStarter.java:207)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:61)
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:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
This is not the solution, just a messy workaround (since it took too much time to solve it):
Uninstall and install the android studio 3.0 again. Do not update the
kotlin plugin and the android studio to newer versions.
Problem
When I try to build my project I get this error
Error:Execution failed for task
':app:transformClassesWithAndroidGradleClassShrinkerForDebug'.
Warnings found during shrinking, please use -dontwarn or -ignorewarnings to suppress them.
My files
app build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
dexOptions {
maxProcessCount = 2
javaMaxHeapSize = "2g"
}
dataBinding {
enabled = true
}
packagingOptions {
exclude 'META-INF/rxjava.properties'
exclude 'META-INF/SearchFilter.properties'
exclude 'META-INF/NOTICE' // will not include NOTICE file
exclude 'META-INF/LICENSE' // will not include LICENSE file
// as noted by #Vishnuvathsan you may also need to include
// variations on the file name. It depends on your dependencies.
// Some other common variations on notice and license file names
exclude 'META-INF/notice'
exclude 'META-INF/notice.txt'
exclude 'META-INF/license'
exclude 'META-INF/license.txt'
}
defaultConfig {
applicationId "com.mt.moviesiwanttowatch"
minSdkVersion 19
targetSdkVersion 26
versionCode 4
versionName "1.2"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//Optional: see how to use the utility.
implementation files('libs/YouTubeAndroidPlayerApi.jar')
implementation 'com.android.support:appcompat-v7:26.0.0-beta2'
implementation "com.android.support:support-v13:26.0.0-beta2"
implementation 'com.android.support:design:26.0.0-beta2'
implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta1'
implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
implementation 'com.google.android.gms:play-services-analytics:11.0.2'
implementation 'com.allattentionhere:fabulousfilter:0.0.2'
implementation 'com.nightonke:boommenu:2.1.0'
implementation 'com.github.Commit451:QuickActionView:2.0.0'
implementation 'com.android.volley:volley:1.0.0'
implementation 'com.nononsenseapps:filepicker:4.1.0'
implementation 'net.simonvt.schematic:schematic:0.7.0'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
implementation 'com.ramotion.cardslider:card-slider:0.1.0'
implementation 'org.jsoup:jsoup:1.10.3'
implementation 'com.google.code.gson:gson:2.8.1'
implementation 'com.squareup.leakcanary:leakcanary-android:1.5.1'
implementation "net.dean.jraw:JRAW:0.9.0"
implementation 'com.gordonwong:material-sheet-fab:1.2.1'
implementation 'com.github.bumptech.glide:glide:4.0.0-RC1'
implementation('com.google.android:flexbox:0.3.0') {
exclude group: 'com.android.support'
}
implementation 'me.drozdzynski.library.steppers:steppers:0.4.0-SNAPSHOT'
implementation 'com.ogaclejapan.smarttablayout:library:1.6.1#aar'
implementation 'com.ogaclejapan.smarttablayout:utils-v4:1.6.1#aar'
implementation 'com.afollestad.material-dialogs:core:0.9.4.5'
implementation 'com.android.support:multidex:1.0.1'
implementation 'com.github.jetradarmobile.desertplaceholder:desertplaceholder:1.2.3'
implementation 'com.github.rubensousa:gravitysnaphelper:1.2'
annotationProcessor 'com.android.databinding:compiler:2.3.3'
annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC1'
annotationProcessor 'net.simonvt.schematic:schematic-compiler:0.7.0'
}
project build.gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha6'
classpath 'com.google.gms:google-services:3.0.0'
}
}
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
maven { url "https://maven.google.com"}
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
and proguard-rules.pro
# Add project specific ProGuard rules here.
# By defaulto, the flags in this file are appended to flags specified
# in C:\Users\CM\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-keep class io.codetail.animation.arcanimator.** { *; }
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
Question
How do I modify my files to fix this problem ?
remove multiDexEnabled true, shrinkResources true, useProguard false
Change minifyEnabled true to minifyEnabled false
Hope this helps.
change buildTypes->debug->minifyEnabled=false
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