【问题标题】:How to test content providers on Android如何在 Android 上测试内容提供者
【发布时间】:2010-11-16 00:34:20
【问题描述】:

我正在尝试使用ProviderTestCase2<T> 测试我的数据库。我可以看到正在创建的测试数据库。因此,我想,经过测试的内容提供者应该使用测试数据库。但是,一旦我尝试对MockContentResolver(或使用newResolverWithContentProviderFromSql 创建的那个)进行任何调用,我就会得到UnsupportedOperationException。这被记录为 MockContentResolver 作为正常行为。因此,我对 ProviderTestCase2 的目的有点不确定。

您如何测试您的内容提供者?

谢谢

【问题讨论】:

    标签: android sqlite junit android-contentprovider


    【解决方案1】:

    据我发现,设置模拟内容解析器不是明确必要的 - 我可能会监督它的情况(可能通过 URI 正确解析提供程序,需要 corect getType() 工作的铰链),但对我来说,这样做就足够了:

    package org.droidcon.apps.template.provider.test;
    
    import org.droidcon.apps.template.provider.ProfileContract;
    import org.droidcon.apps.template.provider.ProfileProvider;
    
    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    import android.test.ProviderTestCase2;
    
    public class ProfileProviderTest extends ProviderTestCase2<ProfileProvider> {
    
        public ProfileProviderTest() {
            super(ProfileProvider.class, ProfileProvider.class.getName());
        }
    
        protected void setUp() throws Exception {
            super.setUp();
        }
    
    
        /**
         * Very basic query test.
         * 
         * Prerequisites: 
         * <ul>
         * <li>A provider set up by the test framework
         * </ul>
         * 
         * Expectations: 
         * <ul>
         * <li> a simple query without any parameters, before any inserts returns a 
         * non-null cursor
         * <li> a wrong uri results in {@link IllegalArgumentException}
         * </ul>
         */
        public void testQuery(){
            ContentProvider provider = getProvider();
    
            Uri uri = ProfileContract.CONTENT_URI;
    
            Cursor cursor = provider.query(uri, null, null, null, null);
    
            assertNotNull(cursor);
    
            cursor = null;
            try {
                cursor = provider.query(Uri.parse("definitelywrong"), null, null, null, null);
                // we're wrong if we get until here!
                fail();
            } catch (IllegalArgumentException e) {
                assertTrue(true);
            }
        }
    }
    

    【讨论】:

    • 网上没有太多关于ProviderTestCase2类的示例代码。这很有帮助。
    • Android documentation 中,他们建议不要直接使用您的内容提供者,而是通过内容解析器。只需阅读我的帖子,了解如何测试内容提供者的更充分示例。
    【解决方案2】:

    我添加此条目是因为我认为它可以帮助想要测试其 Content Provider 的程序员。

    假设您的 Content Provider 称为 MyProvider,并且您有一个名为 MyProviderContract 的合同类定义了一些常量。

    首先,您将编写一个名为MyProviderTestCase 的测试类,它继承自ProviderTestCase2&lt;MyProvider&gt;。您必须定义一个构造函数,该构造函数将调用 super 构造函数:

    public MyProviderTestCase() {
        super(MyProvider.class, MyProviderContract.AUTHORITY);
    }
    

    然后,不要直接使用您的提供程序(避免使用getProvider(),因为您的内容提供程序的用户不会直接访问它),而是使用getMockContentResolver() 获取对内容解析器的引用,然后调用此内容解析器(queryinsert 等)。在下面的代码中,我展示了如何测试insert 方法。

    public void testInsert() {
        Uri uri = MyProviderContract.CONTENT_URI;
        ContentValues values = new ContentValues();
        values.put(MyProviderContract.FIELD1, "value 1");
        values.put(MyProviderContract.FIELD2, "value 2");
        Uri resultingUri = getMockContentResolver().insert(uri, values);
        // Then you can test the correct execution of your insert:
        assertNotNull(resultingUri);
        long id = ContentUris.parseId(resultingUri);
        assertTrue(id > 0);
    }
    

    然后,您可以添加任意数量的测试方法,使用内容解析器而不是直接使用您的内容提供者,就像内容提供者的用户一样。

    【讨论】:

    • 如何运行 ProviderTestCase? Android 单元测试构建变体还是 Instrumentation Test?
    【解决方案3】:

    扩展 ProviderTestCase2 以覆盖 getMockContentResolver() 并返回您自己的从 MockContentResolver 派生的类。

    public class MyProviderTestCase2 extends ProviderTestCase2 {
        @Override
        public MockContentResolver getMockContentResolver () {
            return new MyMockContentResolver();
        }
    }
    

    MyMockContentResolver 将需要覆盖您想要在 ContentProvider 中测试的任何方法。

    那么您应该能够在内容提供者被 ProviderTestCase2 隔离的同时运行任何您想要的测试

    【讨论】:

      【解决方案4】:

      [与问题没有直接关系,但供任何来到这里寻找如何在 android 中测试内容提供者的人将来参考]

      如果使用 API 28 或更高版本,ProviderTestCase2 已从 Android SDK 的默认类路径中删除,因此您需要在 build.gradle 文件中手动添加这些类。

      android {
      
        //libraries added to classpath with useLibrary are being get from Sdk/platforms/android-XX/optional
      
        //adds ProviderTestCase2 to classpath from android.test package that comes with android SDK
        useLibrary 'android.test.runner'
      
        //adds AndroidTestCase to classpath from android.test package that comes with android SDK
        useLibrary 'android.test.base'
      
        //adds MockContentProvider to classpath from android.test.mock package that comes with android SDK
        useLibrary 'android.test.mock'
      
        //if you compiling against 27 or lower you do not need to add useLibrary calls above
        //only from api 28 above those classes were removed from the default classpath
        compileSdkVersion 30
      
      }
      

      然后你可以在你的测试用例中扩展 ProviderTestCase2

      package com.example.samplecontentprovidertest;
      
      import android.test.ProviderTestCase2;
      
      public class ExampleContentProviderTest extends ProviderTestCase2<ExampleContentProvider> {
      
      public ExampleContentProviderTest() {
          super(ExampleContentProvider.class, ExampleContentProvider.AUTHORITY);
      }
      
      public void testUpdate() {
          int affectedRows = getMockContentResolver().update(ExampleContentProvider.SAMPLE_URI, null, null, null);
         //validate update
      }
      
      public void testDelete() {
          int affectedRows = getMockContentResolver().delete(ExampleContentProvider.SAMPLE_URI, null, null);
          //validate insert
      }
      
      }
      

      工作示例:https://github.com/Artenes/android-content-provider-test-sample

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-05
        • 1970-01-01
        • 2023-04-01
        相关资源
        最近更新 更多