Get context of test project in Android junit test case
Asked Answered
R

12

144

Does anyone know how can you get the context of the Test project in Android junit test case (extends AndroidTestCase).

Note: The test is NOT instrumentation test.

Note 2: I need the context of the test project, not the context of the actual application that is tested.

I need this to load some files from assets from the test project.

Roca answered 22/12, 2011 at 14:55 Comment(3)
Why can't you just use InstrumentationTestCase?Sexpartite
Because I am testing services, not UI.Roca
There's a better answer found here: [Using AndroidTestCase instead of a JUnit test][1] [1]: #3171206Monetary
D
189

There's new approach with Android Testing Support Library (currently androidx.test:runner:1.1.1). Kotlin updated example:

class ExampleInstrumentedTest {

    lateinit var instrumentationContext: Context

    @Before
    fun setup() {
        instrumentationContext = InstrumentationRegistry.getInstrumentation().context
    }

    @Test
    fun someTest() {
        TODO()
    }
}

If you want also app context run:

InstrumentationRegistry.getInstrumentation().targetContext

Full running example: https://github.com/fada21/AndroidTestContextExample

Look here: What's the difference between getTargetContext() and getContext (on InstrumentationRegistry)?

Dulcinea answered 17/6, 2015 at 11:52 Comment(10)
Finally an answer on how to use JUnit4 with InstrumentationTest. After hours of searching. Gotta love Android development.Anglicist
Nice! tx (note there is a typo in your class member)Crossbreed
Could someone help about what dependencies need to be added in the gradle file in order for this to work?Crossbreed
Something must have changed. AndroidStudio can't find "AndroidJUnit4" and "InstrumentationRegistry".Mosely
Don't forget to add compile "com.android.support.test:runner:1.0.1" to your gradleWightman
It's deprecated, use InstrumentationRegistry.getInstrumentation().context instead.Rhapsody
@fada21, I'm using import androidx.test.platform.app.InstrumentationRegistry, however the runtime error is occurring 'Unresolved reference: test' on that import within the test directory for a JUnit test.Fetishist
Here is the solution to my issue above with the import. It was related to how the library dependency is added.Fetishist
For my unit test I needed access to the internal application files with context.getFilesDir();. In order to see the files it needs to be Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();.Heptameter
No instrumentation registered! Must run under a registering instrumentation.Circle
M
39

After some research the only working solution seems to be the one yorkw pointed out already. You'd have to extend InstrumentationTestCase and then you can access your test application's context using getInstrumentation().getContext() - here is a brief code snippet using the above suggestions:

public class PrintoutPullParserTest extends InstrumentationTestCase {

    public void testParsing() throws Exception {
        PrintoutPullParser parser = new PrintoutPullParser();
        parser.parse(getInstrumentation().getContext().getResources().getXml(R.xml.printer_configuration));
    }
}
Mayhem answered 15/1, 2012 at 14:17 Comment(2)
Yes but it seems silly that Android does not provide access to the test project context in simple JUnit tests. The context is there in AndroidTestCase.mTestContext but it is private. I don't see why.Roca
@Roca Full Ack - but thats just how it is and I dont like it neither ;)Mayhem
M
25

As you can read in the AndroidTestCase source code, the getTestContext() method is hidden.

/**
 * @hide
 */
public Context getTestContext() {
    return mTestContext;
}

You can bypass the @hide annotation using reflection.

Just add the following method in your AndroidTestCase :

/**
 * @return The {@link Context} of the test project.
 */
private Context getTestContext()
{
    try
    {
        Method getTestContext = ServiceTestCase.class.getMethod("getTestContext");
        return (Context) getTestContext.invoke(this);
    }
    catch (final Exception exception)
    {
        exception.printStackTrace();
        return null;
    }
}

Then call getTestContext() any time you want. :)

Mcgehee answered 9/1, 2013 at 10:16 Comment(3)
Worked perfectly for me and I load assets using Context either of AndroidTestCase via this method, or ActivityInstrumentationTestCase2.getInstrumentation ().getContext () then getResources ().getAssets ()Gadgetry
Can you speculate as to why they made it hidden? If we use this technique, could they take the method away in a later release (breaking our test code)?Overcapitalize
I get java.lang.NoSuchMethodException: android.test.ServiceTestCase.getTestContext()Complemental
G
9

If you want to get the context with Kotlin and Mockito, you can do it in the following way:

val context = mock(Context::class.java)
Grassplot answered 28/9, 2018 at 16:1 Comment(2)
getting null in context?Menchaca
And don't forget to annotate you test class with @RunWith(MockitoJUnitRunner::class)Continuant
I
8

@RunWith(AndroidJUnit4.class) let you use Android Context

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        assertEquals("com.android.systemui", appContext.getPackageName());
    }


}

You can even run it on main thread using runOnMainSync. Here is the complete solution:

@RunWith(AndroidJUnit4::class)
class AwesomeViewModelTest {

    @Test
    fun testHandler() {

        getInstrumentation().runOnMainSync(Runnable {
            val context = InstrumentationRegistry.getInstrumentation().targetContext

          // Here you can call methods which have Handler

       
        })
    }


}
Ima answered 28/10, 2020 at 11:55 Comment(0)
N
7
import androidx.test.core.app.ApplicationProvider;

    private Context context = ApplicationProvider.getApplicationContext();
Nudi answered 22/8, 2019 at 13:17 Comment(0)
M
5

Update: AndroidTestCase This class was deprecated in API level 24. Use InstrumentationRegistry instead. New tests should be written using the Android Testing Support Library. Link to announcement

You should extend from AndroidTestCase instead of TestCase.

AndroidTestCase Class Overview
Extend this if you need to access Resources or other things that depend on Activity Context.

AndroidTestCase - Android Developers

Mayorga answered 6/3, 2016 at 15:56 Comment(0)
L
5

This is to correct way to get the Context. Other methods are already deprecated

import androidx.test.platform.app.InstrumentationRegistry

InstrumentationRegistry.getInstrumentation().context
Librate answered 15/3, 2019 at 13:12 Comment(0)
A
4

For Kotlin unit test with @RunWith(AndroidJUnit4::class)

Add this dependency for kotlin test

implementation 'androidx.test:core-ktx:1.5.0'

In the test class access context using the below snippet.

 private val context = ApplicationProvider.getApplicationContext<Context>()
Acro answered 9/2, 2023 at 21:16 Comment(1)
This answer help me with BitmapFactory.decodeResource(context.resources, resource) Thank you.Stavanger
A
1

For those encountering these problems while creating automated tests, you've gotta do this :

    Context instrumentationContext;

    @Before
    public void method() {

        instrumentationContext = InstrumentationRegistry.getInstrumentation().getContext();

        MultiDex.install(instrumentationContext);
    }
Affrica answered 18/11, 2019 at 1:33 Comment(0)
D
0

The other answers are outdated. Right now every time that you extend AndroidTestCase, there is mContext Context object that you can use.

Demerit answered 12/6, 2016 at 21:3 Comment(0)
F
0

Add Mocito Library

testImplementation 'junit:junit:4.13.2'
testImplementation 'androidx.test:core:1.4.0'
testImplementation 'org.mockito:mockito-core:3.10.0'

Add Annoatation call @Mock where ever need for example for Context

@RunWith(MockitoJUnitRunner::class)

class EmailValidatorTest {

@Mock
private lateinit var context: Context

lateinit var utils:Utils

@Before
fun launch()
{
    utils=Utils(context)
}

@Test
fun emailValidator_NullEmail_ReturnsFalse() {
    assertFalse(utils.isValidEmail(null))
}

}

Fisch answered 21/10, 2021 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.