Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.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 如何使用内容解析器/提供者测试类?_Android_Unit Testing_Final_Android Contentresolver - Fatal编程技术网

Android 如何使用内容解析器/提供者测试类?

Android 如何使用内容解析器/提供者测试类?,android,unit-testing,final,android-contentresolver,Android,Unit Testing,Final,Android Contentresolver,我正在尝试测试查询内容解析器的类 我想使用MockContentResolver和mockquery方法 问题是这种方法是最终的。我该怎么办?使用模拟框架?模仿其他班级?提前谢谢 public class CustomClass { private ContentResolver mContentResolver; public CustomClass(ContentResolver contentResolver) { mContentResolver =

我正在尝试测试查询内容解析器的类

我想使用
MockContentResolver
和mock
query
方法

问题是这种方法是最终的。我该怎么办?使用模拟框架?模仿其他班级?提前谢谢

public class CustomClass {

    private ContentResolver mContentResolver;

    public CustomClass(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    public String getConfig(String key) throws NoSuchFieldException {
        String value = null;

            Cursor cursor = getContentResolver().query(...);
            if (cursor.moveToFirst()) {
                //...
            }
        //..
    }
}

阅读文档后,我能够编写
MockContentProvider
,实现相应游标的返回。然后,我使用
addProvider
将此提供程序添加到
MockContentResolver

下面是一个示例测试,它使用getContentResolver().query从内容提供程序返回模拟数据

它应该适用于任何内容提供商,只需稍作修改,但本例模拟了联系人内容提供商返回的电话号码

以下是一般步骤:
  • 使用MatrixCursor创建适当的游标
  • 扩展MockContentProvider以返回创建的游标
  • 使用addProvider和setContentResolver将提供程序添加到MockContentResolver
  • 将MockContentResolver添加到扩展的MockContext
  • 将上下文传递到被测试的类中
  • 因为查询是最终的方法,所以您不仅需要模拟MockContentProvider,还需要模拟MockContentResolver。否则,在查询方法期间调用acquireProvider时将出现错误

    下面是示例代码:
    这个问题已经很老了,但人们可能仍然像我一样面临这个问题,因为没有太多关于测试这个问题的文档

    对于我来说,对于依赖于内容提供者(来自android API)的测试类,我使用了ProviderTestCase2

    public class ContactsUtilityTest extends ProviderTestCase2<OneQueryMockContentProvider> {
    
    
    private ContactsUtility contactsUtility;
    
    public ContactsUtilityTest() {
        super(OneQueryMockContentProvider.class, ContactsContract.AUTHORITY);
    }
    
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        this.contactsUtility = new ContactsUtility(this.getMockContext());
    }
    
    public void testsmt() {
        String phoneNumber = "777777777";
    
        String[] exampleData = {phoneNumber};
        String[] examleProjection = new String[]{ContactsContract.PhoneLookup.NUMBER};
        MatrixCursor matrixCursor = new MatrixCursor(examleProjection);
        matrixCursor.addRow(exampleData);
    
        this.getProvider().addQueryResult(matrixCursor);
    
        boolean result = this.contactsUtility.contactBookContainsContact(phoneNumber);
        // internally class under test use this.context.getContentResolver().query(); URI is ContactsContract.PhoneLookup.CONTENT_FILTER_URI
        assertTrue(result);
    }
    
    
    }
    
    
    public class OneQueryMockContentProvider extends MockContentProvider {
    private Cursor queryResult;
    
    public void addQueryResult(Cursor expectedResult) {
        this.queryResult = expectedResult;
    }
    
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return this.queryResult;
    }
    }
    
    公共类ContactsUtilityTest扩展了ProviderTestCase2{
    私人接触性;
    公共接触能力测试(){
    super(OneQueryMockContentProvider.class,ContactsContract.AUTHORITY);
    }
    @凌驾
    受保护的void setUp()引发异常{
    super.setUp();
    this.contactsutibility=新的contactsutibility(this.getMockContext());
    }
    公共无效测试SMT(){
    字符串phoneNumber=“777”;
    字符串[]exampleData={phoneNumber};
    字符串[]examleProjection=新字符串[]{ContactsContract.PhoneLookup.NUMBER};
    MatrixCursor MatrixCursor=新MatrixCursor(examleProjection);
    addRow(exampleData);
    this.getProvider().addQueryResult(matrixCursor);
    布尔结果=this.contactsutibility.contactBookContainsContacts(电话号码);
    //测试中的内部类使用此.context.getContentResolver().query();URI是ContactsContract.PhoneLookup.CONTENT\u FILTER\u URI
    资产真实性(结果);
    }
    }
    公共类OneQueryMockContentProvider扩展了MockContentProvider{
    私有游标查询结果;
    public void addQueryResult(游标预期结果){
    this.queryResult=预期结果;
    }
    @凌驾
    公共游标查询(Uri Uri、字符串[]投影、字符串选择、字符串[]selectionArgs、字符串排序器){
    返回此.queryResult;
    }
    }
    
    这是用Jenn Weingarten的答案写的。 需要注意的几件事: -您的
    MockContentProvider
    必须是公共的 -您必须在测试的类中使用方法
    this.getMockContext()
    中的
    Context
    ,而不是
    this.getContext()
    ,否则您将访问设备中的模拟数据,而不是真实数据(在本例中为联系人) -测试不能使用AndroidJUnit4 runner运行 -当然,测试必须作为android指令测试运行 -测试(authority)构造函数中的第二个参数必须和被测试类中查询的URI相同 -模拟提供程序的类型必须作为类参数提供

    基本上,ProviderTestCase2使您能够初始化模拟上下文、模拟内容解析器和模拟内容提供者


    我发现使用旧的测试方法比使用mockito和junit4为高度依赖android api的类编写本地单元测试要容易得多

    我还没有使用Mockito,但对于内容提供商,您可以依赖Robolectric

    您能提供完整的测试用例来测试联系人详细信息获取吗?这是一个不错的解决方案,但是自从API 24以来,
    RenamingDelegatingContext
    已被弃用。
    @Override
     public Context getContext(){
        return new ContextWithMockContentResolver(super.getContext());   
     } 
    
    public class ContactsUtilityTest extends ProviderTestCase2<OneQueryMockContentProvider> {
    
    
    private ContactsUtility contactsUtility;
    
    public ContactsUtilityTest() {
        super(OneQueryMockContentProvider.class, ContactsContract.AUTHORITY);
    }
    
    
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        this.contactsUtility = new ContactsUtility(this.getMockContext());
    }
    
    public void testsmt() {
        String phoneNumber = "777777777";
    
        String[] exampleData = {phoneNumber};
        String[] examleProjection = new String[]{ContactsContract.PhoneLookup.NUMBER};
        MatrixCursor matrixCursor = new MatrixCursor(examleProjection);
        matrixCursor.addRow(exampleData);
    
        this.getProvider().addQueryResult(matrixCursor);
    
        boolean result = this.contactsUtility.contactBookContainsContact(phoneNumber);
        // internally class under test use this.context.getContentResolver().query(); URI is ContactsContract.PhoneLookup.CONTENT_FILTER_URI
        assertTrue(result);
    }
    
    
    }
    
    
    public class OneQueryMockContentProvider extends MockContentProvider {
    private Cursor queryResult;
    
    public void addQueryResult(Cursor expectedResult) {
        this.queryResult = expectedResult;
    }
    
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return this.queryResult;
    }
    }