Ascorbin Ascorbin - 1 month ago 19
Android Question

Getting context in AndroidTestCase or InstrumentationTestCase in Android Studio's Unit Test feature

I got some of my old tests running with Android Studio 1.1.0's new unit test support feature.
When running gradlew testDebug the tests are run, but all of the tests that require a Context fail because

getContext
(AndroidTestCase) /
getInstrumentation.getContext()
(InstrumentationTestCase) both return null.

How can I solve this?

Here's two variants I've tried:

import android.content.Context;
import android.test.InstrumentationTestCase;

public class TestTest extends InstrumentationTestCase {

Context context;

public void setUp() throws Exception {
super.setUp();

context = getInstrumentation().getContext();

assertNotNull(context);

}

public void testSomething() {

assertEquals(false, true);
}

}


and

import android.content.Context;
import android.test.AndroidTestCase;

public class TestTest extends AndroidTestCase {

Context context;

public void setUp() throws Exception {
super.setUp();

context = getContext();

assertNotNull(context);

}

public void testSomething() {

assertEquals(false, true);
}

}


This is my module's
build.gradle
:

apply plugin: 'com.android.application'

android {
compileSdkVersion 22
buildToolsVersion "22.0.0"

testOptions {
unitTests.returnDefaultValues = true
}

defaultConfig {
applicationId "com.example.test.penistest"
minSdkVersion 15
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.0.0'
testCompile 'junit:junit:4.12'
}


and here the
build.gradle
for the project:

// 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.3'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
}
}


EDIT: My tests all worked before upgrading to AS 1.1.0 and ran on a device / emulator.

EDIT:

Heres 2 screenshots of failing InstrumentationTestCase and AndroidTestCase:

enter image description here

enter image description here

Answer

Updated - Newer Examples:

I got these working without deploying to a device. Put the tests in the /src/main/test/ folder.

Here are newer examples, I took your examples and tested them in my own temporary test project. I ran the tests via command line: ./gradlew clean test. Please read more here: https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support.

Top build.gradle:

// 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.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

App build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.0"

    defaultConfig {
        applicationId "com.test"
        minSdkVersion 9
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    testOptions { // <-- You need this
        unitTests {
            returnDefaultValues = true
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'

    testCompile 'junit:junit:4.12' // <-- You need this
}

Basic Tests:

InstrumentationTestCaseTest to test Context and Assertions.

import android.content.Context;
import android.test.InstrumentationTestCase;
import android.test.mock.MockContext;

public class InstrumentationTestCaseTest extends InstrumentationTestCase {

    Context context;

    public void setUp() throws Exception {
        super.setUp();

        context = new MockContext();

        assertNotNull(context);

    }

    public void testSomething() {

        assertEquals(false, true);
    }

}

ActivityTestCase to test your Resources.

import android.content.Context;
import android.content.res.Resources;
import android.test.ActivityTestCase;

public class ActivityTestCaseTest extends ActivityTestCase {

    public void testFoo() {

        Context testContext = getInstrumentation().getContext();
        Resources testRes = testContext.getResources();

        assertNotNull(testRes);
        assertNotNull(testRes.getString(R.string.app_name));
    }
}

AndroidTestCase to test Context and Assertions.

import android.content.Context;
import android.test.AndroidTestCase;
import android.test.mock.MockContext;

public class AndroidTestCaseTest extends AndroidTestCase {

    Context context;

    public void setUp() throws Exception {
        super.setUp();

        context = new MockContext();

        setContext(context);

        assertNotNull(context);

    }

    // Fake failed test
    public void testSomething()  {
        assertEquals(false, true);
    }
}

Googling Old Examples:

After Googling a lot bout this error, I believe your bet is to use getInstrumentation().getContext().getResources().openRawResource(R.raw.your_res). or something similar in order to test your resources.

Using InstrumentationTestCase:

Test Resources:

public class PrintoutPullParserTest extends InstrumentationTestCase {

    public void testParsing() throws Exception {
        PrintoutPullParser parser = new PrintoutPullParser();
        parser.parse(getInstrumentation().getContext().getResources().getXml(R.xml.printer_configuration));
    }
}

Source: http://stackoverflow.com/a/8870318/950427 and http://stackoverflow.com/a/16763196/950427

Using ActivityTestCase:

Test Resources:

public class Test extends ActivityTestCase {

   public void testFoo() {  

      // .. test project environment
      Context testContext = getInstrumentation().getContext();
      Resources testRes = testContext.getResources();
      InputStream ts = testRes.openRawResource(R.raw.your_res);

      assertNotNull(testRes);
   }    
}

Source: http://stackoverflow.com/a/9820390/950427

Using AndroidTestCase:

Getting the Context (a simple hack):

private Context getTestContext() {
    try {
        Method getTestContext = ServiceTestCase.class.getMethod("getTestContext");
        return (Context) getTestContext.invoke(this);
    } catch (final Exception exception) {
        exception.printStackTrace();
        return null;
    }
}

Source: http://stackoverflow.com/a/14232913/950427

But, if you look a the source code of AndroidTestCase, it looks like you need to set a Context yourself:

Source: http://alvinalexander.com/java/jwarehouse/android/core/java/android/test/AndroidTestCase.java.shtml

Comments