我正在尝试编写一个测试用例,以验证写入共享首选项的类。
我正在使用Android Studio v1.5。
在旧版本中,使用AndroidTestCase
时,将第二个apk文件部署到设备,并且可以使用检测上下文运行测试,因此您可以使用检测apk的共享首选项运行测试,而无需更改主apk的现有共享首选项文件。
我整个上午都在努力弄清楚如何在Android Studio测试中获取非null上下文。显然,针对Eclipse进行的单元测试与Android Studio测试框架不兼容,因为调用getContext()
返回null。
我以为已经找到了这个问题的答案:
Get context of test project in Android junit test case
随着时间的推移,事情发生了变化,因为旧版本的Android Studio没有完整的测试支持。因此,很多答案只是骇客。显然现在,您应该像这样编写测试,而不是扩展InstrumentationTestCase
或AndroidTestCase
:
@RunWith(AndroidJUnit4.class)
public class MyTest {
@Test
public void testFoo(){
Context instrumentationContext = InstrumentationRegistry.getContext();
Context mainProjectContext = InstrumentationRegistry.getTargetContext();
}
}
因此,我现在有了一个非null的检测上下文,并且
getSharedPreferences
方法返回了一个似乎有效的实例,但实际上没有编写任何首选项文件。如果我做:
context = InstrumentationRegistry.getContext();
然后,SharedPreferences编辑器将正确写入并提交,并且不会引发任何异常。通过仔细检查,我可以看到编辑器正在尝试写入此文件:
data/data/<package>.test/shared_prefs/PREFS_FILE_NAME.xml
但是永远不会创建或写入文件。
但是使用此:
context = InstrumentationRegistry.getTargetContext();
编辑器可以正常工作,并且首选项已写入此文件:
/data/data/<package>/shared_prefs/PREFS_FILE_NAME.xml
首选项在私有(private)模式下实例化:
SharedPreferences sharedPreferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
据我所知,运行测试后没有将测试apk上传到设备。这可能解释了为什么未使用检测上下文写入文件的原因。此上下文是否有可能是一个伪造的上下文,它会无声地失败?
如果是这种情况,我如何获得REAL工具上下文,以便我可以编写首选项而不更改主项目的首选项?
最佳答案
事实证明,您无法使用检测上下文来写入共享首选项,即使在 eclipse 中也是如此。这将是 eclipse 的等效测试:
import android.content.Context;
import android.content.SharedPreferences;
import android.test.InstrumentationTestCase;
public class SharedPrefsTest extends InstrumentationTestCase {
public void test() throws Exception {
Context context = getInstrumentation().getContext();
String fileName = "FILE_NAME";
SharedPreferences sharedPreferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", "value");
editor.commit();
SharedPreferences sharedPreferences2 = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
assertEquals("value", sharedPreferences2.getString("key", null));
}
}
我只是运行它,它也失败了。首选项永远不会被写入。我认为在这种情况下禁止内部存储文件访问,因为调用
Context.getFilesDir()
会引发InvocationTargetException,在首选项文件上调用File.exists()
也是如此(您可以使用调试器检查编辑器正在写入哪个文件,只需查找一个名为mFile
成员实例中的this.$0
)。因此,我认为这实际上是可能的,这是错误的。尽管我过去曾使用工具上下文进行数据访问层测试,但实际上我们使用了主上下文(
AndroidTestCase.getContext()
),尽管我们为首选项和SQLite文件使用了不同的名称。这就是为什么单元测试没有修改常规应用程序文件的原因。