【问题标题】:Get context of test project in Android junit test case在 Android junit 测试用例中获取测试项目的上下文
【发布时间】:2012-01-26 04:43:44
【问题描述】:

有谁知道如何在 Android junit 测试用例(扩展 AndroidTestCase)中获取 Test 项目 的上下文。

注意:该测试不是仪器测试。

注意 2:我需要测试项目的上下文,而不是被测试的实际应用程序的上下文。

我需要这个来从测试项目的资产中加载一些文件。

【问题讨论】:

  • 为什么不能只使用 InstrumentationTestCase?
  • 因为我在测试服务,而不是 UI。
  • 这里有一个更好的答案:[使用 AndroidTestCase 而不是 JUnit 测试][1] [1]:stackoverflow.com/questions/3170706/…

标签: android junit


【解决方案1】:

Android 测试支持库(目前为androidx.test:runner:1.1.1)提供了新方法。 Kotlin 更新示例:

class ExampleInstrumentedTest {

    lateinit var instrumentationContext: Context

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

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

如果你还想运行应用上下文:

InstrumentationRegistry.getInstrumentation().targetContext

完整运行示例:https://github.com/fada21/AndroidTestContextExample

看这里:What's the difference between getTargetContext() and getContext (on InstrumentationRegistry)?

【讨论】:

  • 终于回答了如何使用 JUnit4 和 InstrumentationTest。经过几个小时的搜索。一定喜欢 Android 开发。
  • 不错! tx(注意你的班级成员有错字)
  • 有人可以帮助了解需要在 gradle 文件中添加哪些依赖项才能使其正常工作吗?
  • 别忘了将compile "com.android.support.test:runner:1.0.1"添加到你的gradle中
  • 已弃用,请改用InstrumentationRegistry.getInstrumentation().context
【解决方案2】:

经过一些研究,唯一可行的解​​决方案似乎是 yorkw 已经指出的那个。您必须扩展 InstrumentationTestCase,然后您可以使用 getInstrumentation().getContext() 访问测试应用程序的上下文 - 这是使用上述建议的简短代码 sn-p:

public class PrintoutPullParserTest extends InstrumentationTestCase {

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

【讨论】:

  • 是的,但是 Android 在简单的 JUnit 测试中不提供对测试项目上下文的访问似乎很愚蠢。上下文在 AndroidTestCase.mTestContext 中,但它是私有的。我不明白为什么。
  • @peceps Full Ack - 但事实就是如此,我也不喜欢它;)
【解决方案3】:

正如您在AndroidTestCase source code 中看到的,getTestContext() 方法是隐藏的。

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

您可以使用反射绕过@hide 注释。

只需在您的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;
    }
}

然后随时致电getTestContext()。 :)

【讨论】:

  • 非常适合我,我使用 Context 通过此方法加载资产,或者使用 AndroidTestCase 或 ActivityInstrumentationTestCase2.getInstrumentation ().getContext () 然后 getResources ().getAssets ()
  • 你能推测他们为什么把它隐藏起来吗?如果我们使用这种技术,他们能否在以后的版本中取消该方法(破坏我们的测试代码)?
  • 我收到java.lang.NoSuchMethodException: android.test.ServiceTestCase.getTestContext()
【解决方案4】:
import androidx.test.core.app.ApplicationProvider;

    private Context context = ApplicationProvider.getApplicationContext();

【讨论】:

    【解决方案5】:

    如果你想用 Kotlin 和 Mockito 获取上下文,可以通过以下方式进行:

    val context = mock(Context::class.java)
    

    【讨论】:

    • 在上下文中为空?
    • 别忘了用@RunWith(MockitoJUnitRunner::class)注释你的测试类
    【解决方案6】:

    更新: AndroidTestCase API 级别 24 中已弃用此类。 请改用InstrumentationRegistry。应使用 Android 测试支持库编写新测试。 Link to announcement

    您应该从 AndroidTestCase 而不是 TestCase 扩展。

    AndroidTestCase 类概述
    如果您需要访问依赖于活动上下文的资源或其他东西,请扩展它。

    AndroidTestCase - Android Developers

    【讨论】:

      【解决方案7】:

      这是获取上下文的正确方法。其他方法已弃用

      import androidx.test.platform.app.InstrumentationRegistry
      
      InstrumentationRegistry.getInstrumentation().context
      

      【讨论】:

        【解决方案8】:

        @RunWith(AndroidJUnit4.class) 让你使用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());
            }
        
        
        }
        

        您甚至可以使用runOnMainSync 在主线程上运行它。这是完整的解决方案:

        @RunWith(AndroidJUnit4::class)
        class AwesomeViewModelTest {
        
            @Test
            fun testHandler() {
        
                getInstrumentation().runOnMainSync(Runnable {
                    val context = InstrumentationRegistry.getInstrumentation().targetContext
        
                  // Here you can call methods which have Handler
        
               
                })
            }
        
        
        }
        

        【讨论】:

          【解决方案9】:

          其他答案已过时。现在每次扩展 AndroidTestCase 时,都有一个 mContext Context 对象可以使用。

          【讨论】:

            【解决方案10】:

            对于那些在创建自动化测试时遇到这些问题的人,你必须这样做:

                Context instrumentationContext;
            
                @Before
                public void method() {
            
                    instrumentationContext = InstrumentationRegistry.getInstrumentation().getContext();
            
                    MultiDex.install(instrumentationContext);
                }
            

            【讨论】:

              【解决方案11】:

              添加 Mocito 库

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

              在需要的地方添加注解调用@Mock,例如用于上下文

              @RunWith(MockitoJUnitRunner::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))
              }
              

              }

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-11-17
                • 1970-01-01
                • 2019-03-05
                • 1970-01-01
                • 2013-07-27
                • 1970-01-01
                • 1970-01-01
                • 2013-09-12
                相关资源
                最近更新 更多