Android instrumentation testing with mockito - android

My question is similar to this one. I am implementing instrumentation testing for my Android project. I want to test the integration by mocking my delegate, so that I can test if delegate methods are called as expected.
My gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.mytest"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
repositories {
maven { url 'http://repo1.maven.org/maven2' }
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.4.0';
compile 'com.android.support:design:23.4.0';
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2';
androidTestCompile 'com.google.dexmaker:dexmaker:1.2';
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.android.support:support-annotations:23.4.0';
androidTestCompile 'com.android.support.test:runner:0.5';
androidTestCompile 'com.android.support.test:rules:0.5';
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2';
}
My Test file:
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
MainActivity mainActivity;
#Mock
MyDelegate delegate;
public MainActivityTest() {
super(MainActivity.class);
}
#Before
public void setUp() throws Exception {
mainActivity = getActivity();
MockitoAnnotations.initMocks(this);
mainActivity.setDelegate(delegate);
}
#Test
public void testDelegateMethod1() throws Exception {
mainActivity.doSomething();
//delegate.method1 should be called
}
}
I got the error:
java.lang.NullPointerException
at com.google.dexmaker.mockito.DexmakerMockMaker.getInvocationHandlerAdapter(DexmakerMockMaker.java:80)
at com.google.dexmaker.mockito.DexmakerMockMaker.getHandler(DexmakerMockMaker.java:75)
at org.mockito.internal.util.MockUtil.isMockitoMock(MockUtil.java:74)
at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:66)
at org.mockito.internal.configuration.injection.scanner.MockScanner.isMockOrSpy(MockScanner.java:86)
at org.mockito.internal.configuration.injection.scanner.MockScanner.preparedMock(MockScanner.java:72)
at org.mockito.internal.configuration.injection.scanner.MockScanner.scan(MockScanner.java:61)
at org.mockito.internal.configuration.injection.scanner.MockScanner.addPreparedMocks(MockScanner.java:47)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:96)
at org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks(InjectingAnnotationEngine.java:62)
at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:56)
at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
Could anyone help with this issue?

Not sure why
MockitoAnnotations.initMocks(this);
cause the crash, I end up with using
System.setProperty("dexmaker.dexcache", InstrumentationRegistry.getTargetContext().getCacheDir().getPath());
instead.

#Captor
private ArgumentCaptor<Callback> CallbackArgumentCaptor;
And then in your test method you will verify that it is called by doing the following:
verify(repository).retrieveSomething(callbackArgumentCaptor.capture());
callbackArgumentCaptor.getValue().successful();
or call failure depends on what you are testing.
Don't forget to add this as well to the #Before
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}

Related

Dagger classes not being generated

I have been trying to include Dagger latest version dagger-android:2.11 in my app. But, Daggerclaases like DaggerAppComponent is not being generated.
following is my app level gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "net.maskery.android.lab.lawyerapp"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
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'
compile 'com.android.support:design:25.3.1'
testCompile 'junit:junit:4.12'
compile 'com.google.dagger:dagger-android:2.11'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'
}
my component interface
#Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
}
my module class
#Module
public class AppModule {
private LawyerApp app;
public AppModule(LawyerApp app) {
this.app = app;
}
#Provides public Context providesContext(){
return app;
}
#Provides public Resources providesResources(){
return app.getResources();
}
}
the app is properly building but when am trying to create AppComponent object, DaggerAppComponent is just not availbale.
I have enabled annotation processing in the settings and created this app only after that.
I tried 'com.neenbedankt.android-apt' plugin too,. This also didnt work for me.
This is like hit-end for me over any options to try here. Please help.

Roboelectric testing

I have never used any kind of JUnit before,so from what I search there is a good tool called roboelectric.
I try to run a simple test as shown in their website but the assertThat() and shadowOf() are not recognised.
Here is the test
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class)
public class MainActivityTest {
#Test
public void clickingLogin_shouldStartLoginActivity() {
MainActivity activity = Robolectric.setupActivity(MainActivity.class);
activity.findViewById(R.id.login).performClick();
Intent expectedIntent = new Intent(activity, LoginActivity.class);
//This line doesn't work.
assertThat(shadowOf(activity).getNextStartedActivity()).
isEqualTo(expectedIntent);
}
}
And this how I set Roboelectric in gradle.
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "testing.theo.robotutorial"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
testCompile "org.robolectric:robolectric:3.0"
}
Any ideas?
Thanks.
Replace with the following assertion will work.
assertTrue(shadowOf(activity).getNextStartedActivity().filterEquals(expectedIntent));
You can refer to answer by Hoisie in Roboelectric github issue #2627 for details.

Android JUnitRunner Empty Test Suite: No Test Results

I'm having trouble running tests in Android Studio. I've read through a load of posts with the same problem here on Stack Overflow, but to no avail. Just to be clear, I want to test in the emulator and not in the JVM.
Run configuration:
Output:
Running tests
Test running startedTest running failed: No test results
Empty test suite.
Build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.0"
defaultConfig {
applicationId "ntnu.stud.markul.crowdshelf"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
// Unit testing dependencies
androidTestCompile ('com.android.support.test:rules:0.3') {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestCompile('com.android.support.test:runner:0.3') {
// Necessary if your app targets Marshmallow (since the test runner
// hasn't moved to Marshmallow yet)
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestCompile 'junit:junit:4.12'
testCompile 'junit:junit:4.12'
}
The test class (located in /src/androidTest/java/com/appname/app/):
#RunWith(AndroidJUnit4.class)
public class NetworkAndDBInstrumentationTest extends ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity mActivity;
public NetworkAndDBInstrumentationTest() {
super(MainActivity.class);
}
#Before
public void setUp() throws Exception {
super.setUp();
// Injecting the Instrumentation instance is required
// for your test to run with AndroidJUnitRunner.
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mActivity = getActivity();
}
#Test
public void typeOperandsAndPerformAddOperation() {
NetworkController.getCrowd("55f01f29f0a5fad2120bb1db");
System.out.print("ok");
Log.d("1TEST", "1TEST");
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
}
I got it to work using this:
#RunWith(AndroidJUnit4.class)
#LargeTest
public class NetworkAndDBInstrumentationTest {
//use the following annotation and declare an ActivityTestRule for your activity under test
#Rule
public ActivityTestRule<RealmActivity> mActivityRule = new ActivityTestRule(RealmActivity.class);
//use #Before to setup your test fixture
#Before
public void setUp() { }
//annotate all test methods with
#Test
public void testGetCrowd() {
Assert.assertEquals(1, 1);
}
#After
public void tearDown() { }
}
Where RealmActivity is the Activity I want to test. Build.gradle and everything else is as in the question post. Now, a follow-up question: What does it matter that I make the #Rule with RealmActivity? Can't I use other Activities in that test? Can I make a Activity-independent test?
Your configuration looks right. You can try to add this to your build.gradle file:
/*
* Working build.gradle test config. Gradle version 1.3.0
*/
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "test.your.app"
minSdkVersion 15
targetSdkVersion 23
versionCode versionMajor * 100 + versionMinor * 10 + versionPatch
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
}
configurations.all {
// Currently espresso is dependent on support-annotations:22.2.1
resolutionStrategy.force 'com.android.support:support-annotations:22.2.1'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
lintOptions {
disable 'SetJavaScriptEnabled'
disable 'InvalidPackage'
abortOnError false
textReport true
textOutput 'stdout'
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/DEPENDENCIES.txt'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
applicationIdSuffix '.debug'
testCoverageEnabled = true
}
release {
}
}
productFlavors {
dev {
versionName "DEV"
}
}
sourceSets { //this one may not be needed. But wont hurt.
androidTest.setRoot('src/androidTest')
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// Android
compile 'com.android.support:design:23.0.1'
compile 'com.android.support:support-v13:23.0.1'
compile 'com.android.support:cardview-v7:23.0.1'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:support-annotations:23.0.1'
// Google Play Services
compile 'com.google.android.gms:play-services-base:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0'
compile 'com.google.android.gms:play-services-appindexing:7.8.0'
// Integration Tests
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2'
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2'
androidTestCompile ('com.android.support.test.espresso:espresso-core:2.2') {
exclude group:'com.android.support', module:'support-v4'
exclude module: 'recyclerview-v7'
}
// Unit Tests
testCompile 'junit:junit:4.12'
testCompile 'com.google.truth:truth:0.25'
//Mocking
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile "com.google.dexmaker:dexmaker:${DEXMAKER_VERSION}"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${DEXMAKER_VERSION}"
androidTestApt "com.google.dagger:dagger-compiler:${DAGGER_VERSION}"
// Set this dependency to use JUnit 4 rules
androidTestCompile 'com.android.support.test:rules:0.3'
androidTestCompile 'com.android.support.test:runner:0.3'
// Leak detection
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
}
You could also try using JUnit 3 style to see if that gets better results. Are you extending ApplicationTestCase? Try and get things working there.
I think you need add this line in your dependencies:
androidTestCompile ('org.hamcrest:hamcrest-library:1.3')

Groovy in Android - how to run Hello world

I'm having trouble referencing a groovy class i've created. Here are the steps:
my build.gradle file has all required dependencies:
apply plugin: 'com.android.application'
apply plugin: 'groovyx.grooid.groovy-android'
android {
compileSdkVersion 22
buildToolsVersion "21.1.2"
packagingOptions {
// workaround for http://stackoverflow.com/questions/20673625/android-gradle-plugin-0-7-0-duplicate-files-during-packaging-of-apk
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/groovy-release-info.properties'
}
defaultConfig {
applicationId "com.example.uen.myrxjavaandroidproject"
minSdkVersion 17
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.netflix.rxjava:rxjava-android:0.20.7'
compile 'com.squareup:otto:1.3.5'
compile 'org.codehaus.groovy:groovy:2.4.3:grooid'
}
And gradle is synched successfully.
then i created a folder under main called 'groovy' such that my project structure looks like the following:
notice i have a groovy class called "Hello", it looks like this:
public class Hello {
String name;
public void sayHello() {
System.out.println("Hello "+getName()+"!");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
now in my MainActivity.java class i try to instantiate Hello class but its not being recognized. I am doing this:
Hello myHello = new Hello();
what am i doing wrong ?
If you want to use a Groovy class from your Java sources, then your Java file must be found in the "groovy" directory. It's done this way to enforce joint compilation (Java classes consuming Groovy classes or the other way).
And independently of this, for the sake of Grooviness, your Hello Groovy class can be reduced to:
class Hello {
String name
void sayHello() {
println "Hello $name!"
}
}

How to run all AndroidTests with Gradle?

I use Android Studio 1.1.0 and created a new Android project. AS creates this new project with one ApplicationTest. When I call:
$ ./gradlew clean createDebugCoverageReport
this ApplicationTest is executed. Now I added a new test:
public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity>
But this new test isn't executed. Whats going wrong? Both test classes are in the same folder:
app\src\androidTest\java\eu.the4thfloor.testapp\
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "eu.the4thfloor.testapp"
minSdkVersion 10
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
jacoco {
version = '0.7.3.201502191951'
}
buildTypes {
debug {
testCoverageEnabled true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
The problem was the wrong constructor.
AS suggested this one:
public ActivityTest(Class<MainActivity> activityClass) {
super(activityClass);
}
But with this constructor the test isn't executed. You have to use this constructor:
public ActivityTest() {
super(MainActivity.class);
}
The complete test class looks like this:
import android.test.ActivityInstrumentationTestCase2;
public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public ActivityTest() {
super(MainActivity.class);
}
public void test2() {
assertTrue(true);
}
}
Give only
./gradlew test
a try.

Categories

Resources