Android Studio:无法在检测测试中写入共享首选项

Mis*_*ith 15 instrumentation android unit-testing android-context android-studio

我正在尝试编写一个测试用例来验证写入共享首选项的类.我正在使用Android Studio v1.5.

在良好的旧日食中,使用时AndroidTestCase,第二个apk文件被部署到设备,并且可以使用检测上下文运行测试,因此您可以使用检测apk的共享首选项运行测试,而无需更改主apk的现有共享首选项文件.

我花了整个上午试图弄清楚如何在Android Studio测试中获得非空上下文.显然,为eclipse进行的单元测试与Android Studio测试框架不兼容,因为调用getContext()返回null.我以为我在这个问题中找到了答案: 在Android junit测试用例中获取测试项目的上下文

随着旧版本的Android Studio没有完整的测试支持,事情已经发生了变化.所以很多答案都只是黑客攻击.显然现在不是扩展InstrumentationTestCase,AndroidTestCase你应该像这样编写测试:

@RunWith(AndroidJUnit4.class)
public class MyTest {

    @Test
    public void testFoo(){
        Context instrumentationContext = InstrumentationRegistry.getContext();
        Context mainProjectContext = InstrumentationRegistry.getTargetContext();            
    }   
}
Run Code Online (Sandbox Code Playgroud)

所以我现在有一个非null的检测上下文,并且该getSharedPreferences方法返回一个似乎有效的实例,但实际上没有写入首选项文件.

如果我做:

context = InstrumentationRegistry.getContext();      
Run Code Online (Sandbox Code Playgroud)

然后,SharedPreferences编辑器正确写入和提交,不会抛出任何异常.仔细观察后,我可以看到编辑器正在尝试写入此文件:

data/data/<package>.test/shared_prefs/PREFS_FILE_NAME.xml
Run Code Online (Sandbox Code Playgroud)

但是文件永远不会被创建或写入.

但是使用这个:

context = InstrumentationRegistry.getTargetContext(); 
Run Code Online (Sandbox Code Playgroud)

编辑器正常工作,并将首选项写入此文件:

/data/data/<package>/shared_prefs/PREFS_FILE_NAME.xml
Run Code Online (Sandbox Code Playgroud)

首选项以私有模式实例化:

SharedPreferences sharedPreferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
Run Code Online (Sandbox Code Playgroud)

据我所知,运行测试后没有测试apk上传到设备.这可能解释了为什么文件不是使用检测上下文编写的.这个上下文是否可能是一个无声地失败的虚假上下文?

如果是这种情况,我怎样才能获得真实的仪器上下文,以便我可以在不改变主项目偏好的情况下编写首选项

Mis*_*ith 5

事实证明,您无法使用检测上下文写入共享首选项,即使在 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));
    }
}
Run Code Online (Sandbox Code Playgroud)

我刚刚运行它,它也失败了。首选项永远不会被写入。我认为在这种情况下禁止内部存储文件访问,因为调用Context.getFilesDir()会引发 InvocationTargetException,调用File.exists()首选项文件也是如此(您可以使用调试器检查编辑器写入哪个文件,只需查找mFile内部调用的私有变量this.$0成员实例)。

所以我错误地认为这实际上是可能的。我虽然过去在数据访问层测试中使用了检测上下文,但实际上我们使用了主上下文 ( AndroidTestCase.getContext()),尽管我们对首选项和 SQLite 文件使用了不同的名称。这就是单元测试没有修改常规应用程序文件的原因。