- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
2012 年 2 月 13 日更新:接受了答案,解释说这种行为是一个错误,并指出它似乎在比 v 1.6 更好的模拟器上消失了,这对我们大多数人来说都不是问题。解决方法是简单地循环/休眠,直到 getContext().getApplicationContext() 返回非空值。结束更新
根据 android.app.Application javadoc,我定义了一个单例(称为数据库),我的所有 Activity 都可以访问它以获取状态和持久数据,并且 Database.getDatabase(Context) 通过 Context.getApplicationContext() 获取应用程序上下文。当 Activity 将自身传递给 getDatabase(Context) 时,此设置就像宣传的那样工作,但是当我从 AndroidTestCase 运行单元测试时,getApplicationContext() 调用通常返回 null,尽管测试时间越长,它返回非 null 的频率越高值(value)。
以下代码在 AndroidTestCase 中重现了 null —— 演示不需要单例。
首先,为了记录应用实例化消息,我在被测应用中定义了 MyApp 并将其添加到 list 中。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Log.i("MYAPP", "this=" + this);
Log.i("MYAPP", "getAppCtx()=" + getApplicationContext());
}
}
接下来,我定义了一个测试用例报告 AndroidTestCase.getContext() 4 次,由一些 sleep 和 getSharedPreferences() 调用分隔:
public class DatabaseTest extends AndroidTestCase {
public void test_exploreContext() {
exploreContexts("XPLORE1");
getContext().getSharedPreferences("foo", Context.MODE_PRIVATE);
exploreContexts("XPLORE2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
exploreContexts("XPLORE3");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
exploreContexts("XPLORE4");
}
public void exploreContexts(String tag) {
Context testContext = getContext();
Log.i(tag, "testCtx=" + testContext +
" pkg=" + testContext.getApplicationInfo().packageName);
Log.i(tag, "testContext.getAppCtx()=" + testContext.getApplicationContext());
try {
Context appContext = testContext.createPackageContext("com.foo.android", 0);
ApplicationInfo appInfo = appContext.getApplicationInfo();
Log.i(tag, "appContext=" + appContext +
" pkg=" + appContext.getApplicationInfo().packageName);
Log.i(tag, "appContext.getAppCtx()=" + appContext.getApplicationContext());
} catch (NameNotFoundException e) {
Log.i(tag, "Can't get app context.");
}
}
}
这是生成的 logCat 的一部分(SDK11 WinXP 上的 1.6 模拟器,通过 Eclipse):
INFO/TestRunner(465): started: test_exploreContext(test.foo.android.DatabaseTest)
INFO/XPLORE1(465): testCtx=android.app.ApplicationContext@43757368 pkg=com.foo.android
INFO/XPLORE1(465): testContext.getAppCtx()=null
INFO/XPLORE1(465): appContext=android.app.ApplicationContext@437801e8 pkg=com.foo.android
INFO/XPLORE1(465): appContext.getAppCtx()=null
INFO/XPLORE2(465): testCtx=android.app.ApplicationContext@43757368 pkg=com.foo.android
INFO/XPLORE2(465): testContext.getAppCtx()=null
INFO/XPLORE2(465): appContext=android.app.ApplicationContext@43782820 pkg=com.foo.android
INFO/XPLORE2(465): appContext.getAppCtx()=null
INFO/MYAPP(465): this=com.foo.android.MyApplication@43783830
INFO/MYAPP(465): getAppCtx()=com.foo.android.MyApplication@43783830
INFO/XPLORE3(465): testCtx=android.app.ApplicationContext@43757368 pkg=com.foo.android
INFO/XPLORE3(465): testContext.getAppCtx()=com.foo.android.MyApplication@43783830
INFO/XPLORE3(465): appContext=android.app.ApplicationContext@43784768 pkg=com.foo.android
INFO/XPLORE3(465): appContext.getAppCtx()=com.foo.android.MyApplication@43783830
INFO/XPLORE4(465): testCtx=android.app.ApplicationContext@43757368 pkg=com.foo.android
INFO/XPLORE4(465): testContext.getAppCtx()=com.foo.android.MyApplication@43783830
INFO/XPLORE4(465): appContext=android.app.ApplicationContext@43785778 pkg=com.foo.android
INFO/XPLORE4(465): appContext.getAppCtx()=com.foo.android.MyApplication@43783830
INFO/TestRunner(465): finished: test_exploreContext(test.foo.android.DatabaseTest)
请注意,getApplicationContext() 有一段时间返回 null,然后开始返回 MyApp 的一个实例。我无法在此测试的不同运行中获得完全相同的结果(这就是我最终进行 4 次迭代、休眠以及调用 getSharedPreferences() 以尝试使应用程序存在的方式)。
上面的 LogCat 消息 block 似乎最相关,但是单个测试的单个运行的整个 LogCat 很有趣。 Android 启动了 4 个 AndroidRuntimes;上面的 block 是从 4 开始的。有趣的是,第三个运行时显示的消息表明它在进程 ID 447 中实例化了一个不同的 MyApp 实例:
INFO/TestRunner(447): started: test_exploreContext(test.foo.android.DatabaseTest)
INFO/MYAPP(447): this=com.foo.android.MyApplication@437809b0
INFO/MYAPP(447): getAppCtx()=com.foo.android.MyApplication@437809b0
INFO/TestRunner(447): finished: test_exploreContext(test.foo.android.DatabaseTest)
我假设 TestRunner(447) 消息来自父测试线程,报告进程 465 中的子进程。不过,问题是:为什么 Android 让 AndroidTestCase 在其上下文正确连接到应用程序实例之前运行?
解决方法:如果我调用 getContext().getSharedPreferences("anyname", Context.MODE_PRIVATE).edit().clear ().commit();
首先,所以我会这样做。
顺便说一句:如果答案是“这是一个 Android 错误,你为什么不提交它;哎呀,你为什么不修复它?”那么我愿意两者都做。我还没有迈出成为错误提交者或贡献者的一步——也许现在是个好时机。
最佳答案
Instrumentation 在与主应用线程不同的线程中运行,因此它可以在不阻塞或中断(或被阻塞)主线程的情况下执行。如果需要与主线程同步,例如:Instrumentation.waitForIdleSync()
特别是,Application 对象以及所有其他顶级类(如 Activity)都由主线程初始化。您的检测线程在初始化的同时运行。如果您正在接触这些对象中的任何一个并且没有实现您自己的线程安全措施,您可能应该在主线程上运行这样的代码,例如通过:Instrumentation.runOnMainSync(java.lang.Runnable)
关于android - 为什么AndroidTestCase.getContext().getApplicationContext() 返回null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6516441/
https://gist.github.com/blundell/ff2ac1d5ff0a41519c36 http://developer.android.com/reference/android
我已经实现了一个 Instrumentation 和一个 AndroidTestCase。 对于我的测试,我需要连接到外部 WIFI 设备。我希望测试人员能够指定一个 SSID 供测试使用。 给命令行
我打算开始编写一些 android 测试用例,我想知道是否有一种方法可以在模拟器中以编程方式打开和关闭连接。 // High level puesdo code Test: is Message Pu
希望在方法 assertActivityRequiresPermission 和 assertReadingContentUriRequiresPermission 方面得到一些帮助。它的行为方式与我
我找到了 MeediaMuxer 的演示,它是一个 AndroidTestCase 文件。这是 link . 我从未使用过 Android Test。我做了一些研究,但其中大部分都有些复杂......
我正在使用 ActivityInstrumentationTestCase2 在我的 GUI 上进行自动黑盒测试。有没有办法点击一个对话框,或者在单元测试中获取属于该对话框的 View ? 我能想出的
我正在编写一个 android 测试用例,它需要对被测试的 Activity 执行一个单独的 Activity(不是为了测试,而是为了获得对 contentresolver 的访问权限,以便我可以更改
我一直在看这个答案:https://stackoverflow.com/a/2055455/281460它很好地解释了可用于 Android 单元/集成测试的不同测试类。不过,它没有解释的一件事是 I
我正在编写一些测试来测试我的 sqllite 数据库代码。这里有人可以解释一下,使用我从 AndroidTestCase.getContext() 获得的上下文来编写这些测试是否会有所不同?或使用 I
我正在使用 AndroidTestCase 进行一些单元测试,并且想知道是否可以使用我为 junit4 读过的忽略注释?仅仅使用注解就会报错,也许有什么特别需要注意的地方? 提前谢谢,马库斯 最佳答案
在为 Android 库项目编写测试用例时,我遇到了一些 View 尺寸问题。具体来说,我正在使用 AndroidTestCase 来测试自定义 View 类,该类(除其他外)可以生成其内容的位图。创
在我的项目中,当Service启动时,我发送一个广播: Intent intent = new Intent("my.service.action"); intent.setPackage("com.
我正在尝试在 Android 测试中测试写入 Parcel,但它不起作用。 s==空!怎么了? public class scraptest extends AndroidTestCase {
我正在为我的 Android 项目编写一个非常简单的单元测试用例,测试用例简单地执行一个在后台进行网络操作的 AsyncTask。我正在为我的测试用例扩展 AndroidTestCase 类: pub
我正在尝试使用 AndroidTestCase 进行测试。我试图在我的应用程序中只测试一个特定的类,但是这个类不扩展 Activity、Service 或其他任何东西。除了需要上下文之外,它基本上是一
我有一个测试用例,并在那里使用Environment.getExternalStorageDirectory() 调用,它返回 null。 我在应用程序的 list 中拥有“写入外部存储”权限(并且
我正在尝试执行一个扩展我制作的 AndroidTestCase 的测试类,但显然我一直收到以下错误: No apk changes detected. Skipping file upload, fo
你好,我正在为我的 sqlite 数据库做测试部分。我以前使用过 JUnit,但我了解到我必须扩展 AndroidTestCase 才能获得模拟上下文。但是,当我 try catch 异常时(如在 J
我正在尝试接受 Android Studio 的新单元测试功能。我已按照 http://tools.android.com/tech-docs/unit-testing-support 上的说明进行操
我有自己的 SQLiteOpenHelper 如下: public class MyOpenHelper extends SQLiteOpenHelper { public static fina
我是一名优秀的程序员,十分优秀!