Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/202.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Studio:无法在插入指令的测试中写入共享首选项_Android_Unit Testing_Android Studio_Android Context_Instrumentation - Fatal编程技术网

Android Studio:无法在插入指令的测试中写入共享首选项

Android Studio:无法在插入指令的测试中写入共享首选项,android,unit-testing,android-studio,android-context,instrumentation,Android,Unit Testing,Android Studio,Android Context,Instrumentation,我正在尝试编写一个测试用例来验证一个写入共享首选项的类。 我使用的是Android Studio v1.5 在旧的eclipse中,当使用AndroidTestCase时,第二个apk文件被部署到设备上,并且可以使用检测上下文运行测试,因此您可以使用检测apk的共享首选项运行测试,而无需更改主apk的现有共享首选项文件 我花了一上午的时间试图找出如何在Android Studio测试中获得非空上下文。显然,为eclipse进行的单元测试与Android Studio测试框架不兼容,因为调用get

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

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

我花了一上午的时间试图找出如何在Android Studio测试中获得非空上下文。显然,为eclipse进行的单元测试与Android Studio测试框架不兼容,因为调用
getContext()
返回null。 我想我已经找到了这个问题的答案:

随着时间的推移,情况发生了变化,因为旧版本的Android Studio没有完全的测试支持。所以,很多答案都是胡编乱造的。显然,现在不应该扩展
InstrumentationTestCase
AndroidTestCase
,而应该这样编写测试:

@RunWith(AndroidJUnit4.class)
public class MyTest {

    @Test
    public void testFoo(){
        Context instrumentationContext = InstrumentationRegistry.getContext();
        Context mainProjectContext = InstrumentationRegistry.getTargetContext();            
    }   
}
现在我有了一个非空的插装上下文,该方法返回一个似乎有效的实例,但实际上没有编写首选项文件

如果我这样做:

context = InstrumentationRegistry.getContext();      
然后SharedReferences编辑器正确写入和提交,并且不会引发异常。仔细检查后,我可以看到编辑器正在尝试写入此文件:

data/data/<package>.test/shared_prefs/PREFS_FILE_NAME.xml
/data/data/<package>/shared_prefs/PREFS_FILE_NAME.xml
编辑器工作正常,首选项写入此文件:

data/data/<package>.test/shared_prefs/PREFS_FILE_NAME.xml
/data/data/<package>/shared_prefs/PREFS_FILE_NAME.xml
据我所知,在运行测试后,没有将测试apk上传到设备。这可能解释了为什么不使用检测上下文编写文件。这个上下文是否可能是一个假上下文,它会自动失败


如果是这样的话,我如何才能获得一个真正的插装上下文,这样我就可以在不改变主项目首选项的情况下编写首选项?

请注意,您仍然可以使用Android Studio运行旧式测试,这些测试扩展了
插装测试用例
AndroidTestCase
,或者Android Studio中的ActivityInstrumentationTestCase2


新的测试支持库提供了对单个活动的功能测试。我认为,在尝试获取测试所用的
工具和/或
上下文之前,您需要创建其中一个对象。有一个使用此类的示例。

如果您想在不创建活动的情况下测试类,我发现使用Robolectric最简单。Robolectric为您提供了一个模拟上下文,它完成了上下文所做的一切。事实上,这是我使用Robolectric进行单元测试的主要原因

仪器将与应用程序一起安装。应用程序将自行运行,从而读取和写入自己的
SharedReferences

奇怪的是,
Instrumentation
SharedReferences
被删除(或从未创建),但即使它们被创建,您也很难将它们传递到被测试的应用程序中。如上所述,只需调用
context.getSharedReferences()仍将提供实际的应用程序首选项,而不是您的指令插入

您需要找到一种方法来为您的测试应用程序提供首选项。解决此问题的一个好方法是将首选项保留在
应用程序中,如下所示:

public class App extends Application {
    SharedPreferences mPreferences;
    public void onCreate() {
        mPreferences = getSharedPreferences(fileName, Context.MODE_PRIVATE);
    }

    // add public getter / setter
}
这样,你可以

  • 只要您有一个上下文,就可以使用
    ((App)context.getApplicationContext()).getPreferences()从单个源获取首选项
  • 在运行测试和开始任何注入测试数据的活动之前,请自己设置首选项
  • 在您的测试设置中,然后调用以下命令以注入您需要的任何首选项

    @Before
    public void before() {
        ((App) InstrumentationRegistry.getTargetContext()).setPreferences(testPreferences);
    }
    
    确保在每个测试之后正确地完成活动,以便每个测试都可以获得它们自己的依赖关系


    此外,您应该强烈考虑使用Mockito和其他框架模拟
    SharedPreferences
    ,或者自己实现
    SharedPreferences
    接口,因为这大大简化了与模型的交互验证。

    结果表明,您无法使用检测上下文写入共享首选项,即使在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()
    首选项文件也会引发InvocationTargetException(您可以使用调试器检查编辑器正在写入哪个文件,只需在
    this.$0
    成员实例中查找名为
    mFile
    的私有变量即可)


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

    您的测试是在
    test
    目录下还是在
    testAndroid
    下?请注意,您仍然可以运行扩展
    InstrumentationTestCase
    AndroidTestCase的旧测试
    在Android Studio中。@code Peedient此测试在androidTest文件夹下。是的,您仍然可以使用
    InstrumentationTestCase
    AndroidTestCase
    ,但Google已经破坏了这两个测试,并且
    getContext
    返回空值。您说“破坏”是什么意思?我已成功地将现有项目中的所有测试移植到Android Studio中。@史密斯先生,您如何为您的被测类提供