Search code examples
androidunit-testingandroid-gradle-pluginandroid-sqlitejunit4

How to unit test with ContentValues always null vs Method getAction in android.content.Intent not mocked


Recently I've been unit testing doing an update using the latest android studio, which is 3 beta 6, and I've found that even when I initialize a ContentValues it is null. I need it to actually be a value / init-ed ContentValues.

my gradle file:

apply plugin: 'com.android.application'

android {

    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "com.cubedelement.soundplanner"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "org.mockito.testInstrumentationRunner"
        vectorDrawables.useSupportLibrary = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        targetCompatibility 1.8
        sourceCompatibility 1.8
    }

    testOptions {
        unitTests.returnDefaultValues = true
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:palette-v7:26.1.0'
    androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.0', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    implementation 'com.google.dagger:dagger-android:2.11'
    implementation 'com.google.dagger:dagger-android-support:2.11' // if you use the support libraries
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.11'

    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test:rules:1.0.1'
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.google.code.gson:gson:2.8.0'
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.powermock:powermock-api-mockito2:1.7.0'
    testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'org.mockito:mockito-core:2.8.47'
    androidTestImplementation 'org.mockito:mockito-core:2.8.47'
}

but wait, there's more!

So I've also got a simple test which is:

import android.content.ContentValues;

public class Test {
    @Test public void ContentValuesShouldNotBeNull(){
         ContentValues v = new ContentValues();
         assertEquals(v, null) // this is true, but I don't want it to be, help!
    }
}

here is the view in android studio android beta showing null for content values

So I've tried a default gradle file and found that contentvalues is not null.

here is the file:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion '26.0.1'
    defaultConfig {
        applicationId "com.example.kelly_vernon.myapplication"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

I honestly don't understand gradle a lot at this point, but I do know that my config, which is a bunch of ideas to support dagger and other values is not great by any stretch.

After trying other things, I found this to be the culprit:

testOptions {
    unitTests.returnDefaultValues = true
}

I figured out the reason why I had this. I have a test in another area that is testing intents, and I need the default.

Is there a way to restrict this to exclude ContentValues or the inverse to not include the Intent?


Solution

  • Well, it's solved. At the time of this writing, you still cannot do unit testing against android content classes like ContentValues and Intents.

    Because of this, I've have introduced Robolectric. It's not difficult, but here are the changes.

    the gradle file:

    testOptions {
        unitTests {
            returnDefaultValues = true
            includeAndroidResources = true // new line
        }
    }
    

    The test:

    import android.content.ContentValues;
    
    @RunWith(RobolectricTestRunner.class) //new line to start robolectric
    public class Test {
        @Test public void ContentValuesShouldNotBeNull(){
             ContentValues v = new ContentValues();
             assertNotNull(v, null);
        }
    }