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

2023-12-21

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

我想用MockContentResolver并嘲笑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()) {
                //...
            }
        //..
    }
}

下面是一个使用 getContentResolver().query 从内容提供者返回模拟数据的示例测试。

它应该适用于任何内容提供商,只需进行一些修改,但此示例模拟从联系人内容提供商返回的电话号码

以下是一般步骤:

  1. 使用 MatrixCursor 创建适当的光标
  2. 扩展 MockContentProvider 以返回创建的游标
  3. 使用 addProvider 和 setContentResolver 将提供程序添加到 MockContentResolver
  4. 将 MockContentResolver 添加到扩展的 MockContext
  5. 将上下文传递到被测试的类中

因为query是final方法,所以你不仅需要模拟MockContentProvider,还需要模拟MockContentResolver。否则在查询方法期间调用 acquireProvider 时会出现错误。

这是示例代码:

public class MockContentProviderTest extends AndroidTestCase{
    public void testMockPhoneNumbersFromContacts(){
        //Step 1: Create data you want to return and put it into a matrix cursor
        //In this case I am mocking getting phone numbers from Contacts Provider
        String[] exampleData = {"(979) 267-8509"}; 
        String[] examleProjection = new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER};
        MatrixCursor matrixCursor = new MatrixCursor(examleProjection);
        matrixCursor.addRow(exampleData);

        //Step 2: Create a stub content provider and add the matrix cursor as the expected result of the query
        HashMapMockContentProvider mockProvider = new HashMapMockContentProvider();
        mockProvider.addQueryResult(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, matrixCursor);

        //Step 3: Create a mock resolver and add the content provider.
        MockContentResolver mockResolver = new MockContentResolver();
        mockResolver.addProvider(ContactsContract.AUTHORITY /*Needs to be the same as the authority of the provider you are mocking */, mockProvider);

        //Step 4: Add the mock resolver to the mock context
        ContextWithMockContentResolver mockContext = new ContextWithMockContentResolver(super.getContext());
        mockContext.setContentResolver(mockResolver);

        //Example Test 
        ExampleClassUnderTest underTest = new ExampleClassUnderTest();
        String result = underTest.getPhoneNumbers(mockContext);
        assertEquals("(979) 267-8509",result);
    }

    //Specialized Mock Content provider for step 2.  Uses a hashmap to return data dependent on the uri in the query
     public class HashMapMockContentProvider extends MockContentProvider{
         private HashMap<Uri, Cursor> expectedResults = new HashMap<Uri, Cursor>();
         public void addQueryResult(Uri uriIn, Cursor expectedResult){
             expectedResults.put(uriIn, expectedResult);
         }
         @Override
         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
                return expectedResults.get(uri);
         } 
     }

     public class ContextWithMockContentResolver extends RenamingDelegatingContext {
            private ContentResolver contentResolver;
            public void setContentResolver(ContentResolver contentResolver){ this.contentResolver = contentResolver;}
            public ContextWithMockContentResolver(Context targetContext) { super(targetContext, "test");}
            @Override public ContentResolver getContentResolver() { return contentResolver; }
            @Override public Context getApplicationContext(){ return this; } //Added in-case my class called getApplicationContext() 
     }

     //An example class under test which queries the populated cursor to get the expected phone number 
     public class ExampleClassUnderTest{
         public  String getPhoneNumbers(Context context){//Query for  phone numbers from contacts
                String[] projection = new String[]{ ContactsContract.CommonDataKinds.Phone.NUMBER};
                Cursor cursor= context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null);
                cursor.moveToNext();
                return cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
         }
     }
}

如果您不想传递上下文:

如果你想让被测试的类中的 getContext() 返回它而不是传递它,你应该能够在你的 android 测试中重写 getContext() ,如下所示

@Override
 public Context getContext(){
    return new ContextWithMockContentResolver(super.getContext());   
 } 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用内容解析器/提供者测试类? 的相关文章

  • 删除视图并重新创建它

    有没有办法删除设置的视图 setContentView R layout set map center mapView MapView findViewById R id mapview 如果我再次调用此视图 则会收到一条错误消息 java
  • 如何使用gradle这样的格式更改apk名称?

    当我使用 gradle 构建应用程序时 我想将 app release apk 文件名更改为如下所示 format appname of package name V version code yyMMdd R T explain appn
  • 居中复选框视图

    如果除了 或代替 复选框之外 您还对单选按钮感兴趣 请参阅this https stackoverflow com questions 16701806 centering views 2而是提问 尽管存在
  • 删除 json 对象字符串中的“\”

    如何删除下面字符串中的特殊字符 String x message content toom recipients id 1000001865 room subject room 我使用了 x replaceAll 但它不起作用 您必须转义正
  • Android-全屏视频视图

    我正在尝试使此 VideoView 以全屏模式显示 public class ViewVideo extends Activity private String filename private static final int INSER
  • 有没有办法替代Android中的标准Log?

    有没有办法以某种方式拦截对 android 中标准 Log 的调用并执行其他操作 在桌面 Java 中 人们通常会得到一些记录器 因此有多种方法可以安装不同的日志处理程序 实现 但是 Android似乎对Log有静态调用 我找不到任何有关替
  • 如何在我的 Android 应用程序中实现应用内购买?

    如何在我的 Android 应用程序中实现应用内购买 我提到 http developer android com guide market billing billing integrate html billing service ht
  • 无论如何,要控制宋何时选择Android.bp,何时不选择?

    使用新的构建系统 即 Soong 安卓取代Android mk with Android bp 还有 Android Q 及以上版本 Soong将选择所有Android bp文件 无论所有文件都存在于何处 早些时候 对于 2 级和 3 级模
  • 错误 libGL.so:无法使用 Android 模拟器打开共享对象文件

    我试图在 Ubuntu 12 04 64 位 中运行 android 模拟器 但是 我收到以下错误 Starting emulator for AVD emulatr Failed to load libGL so error libGL
  • AOSP 中 android.Build.SERIAL 何时何地生成?

    我知道android Build SERIAL是在第一次设备启动时生成的 但我无法准确定位位置和时间 我正在建造AOSP Jelly Bean Android平板电脑 nosdcard 第二个问题 这个是序列号吗 really对所有人来说都
  • 当编辑文本获得焦点时更改边框颜色

    我想知道当编辑文本聚焦时如何更改它的边框颜色 目前它看起来像这样 我尝试过在SDK中检查源图片 但我无法理解它 我也尝试过使用xml 但无法仅更改边框颜色 如果我找到源图片 我可以在 Photoshop 中编辑以更改颜色 有什么关于如何执行
  • opencv人脸检测示例

    当我在设备上运行应用程序时 应用程序崩溃并显示以下按摩 java lang UnsatisfiedLinkError 无法加载 detector based tracker findLibrary 返回 null 我正在使用 OpenCV
  • 使用 DiffUtil 在 RecyclerView 上添加拖放

    我有一个从房间数据库更新的列表 我从 Room 收到更新的数据作为新列表 然后将其传递给列表适配器 https developer android com reference androidx recyclerview widget Lis
  • 活动组代码示例

    有人可以给我一些使用活动组的示例代码吗 我的应用程序中有一些按钮 我想将活动应用于这些按钮 目前我正在使用 setVisibility 但我被告知活动组将是更好的选择 这是另一个ActivityGroup 示例项目 http richipa
  • 确定视图是否在屏幕上 - Android

    我对这个有点困惑 首先也是最重要的是 以下链接很有用 但是我提出了一些可见性问题 链接 检查视图可见性 https stackoverflow com questions 4628800 android how to check if a
  • Android:如何在布局中放置纯色矩形?

    我有一个可以很好地膨胀的relativelayout 我想在顶部添加一个跨越布局宽度的纯色矩形 我尝试将以下内容放入我的 xml 中
  • SQLiteDatabase.openDatabase 与 SQLiteOpenHelper.getReadableDatabase

    这两种方法有什么区别吗 两者都返回一个打开的 SQLiteDatabase 如果数据库不存在 两者都可以创建数据库 当需要读 写时 SQLiteOpenHelper 还具有 getWriteableDatabase 我应该使用哪种方法以及在
  • Android BLE 扫描永远找不到设备

    几天以来 我尝试在我的应用程序中实现 BLE 连接 我知道我尝试连接的设备功能齐全 因此问题一定是我的代码 我用BluetoothLeScanner startScan 方法 但回调方法永远不会被调用 public void startSc
  • 如何让用户在android列表视图中选择主题?

    我有一个带有两个标签的列表视图 标题和副标题 我想要深色和浅色背景作为用户选项 标题具有 textAppearanceMedium 副标题具有 textAppearanceSmall 我希望样式 MyTheme Dark 具有白色文本 My
  • 我可以通过在 Android Activity 中声明适当的成员“静态”来提高效率吗

    如果一个 Activity 在实践中是单例 我认为我可以通过声明适当的成员 静态 来获得一些效率 且风险为零 是的 The Android 文档说 http developer android com guide topics fundam

随机推荐

  • Excel VBA 具有多个搜索条件并循环,直到找到所有不同的结果

    我对 VBA 非常陌生 并且截止日期非常短 因此如果我没有遵循所有论坛指南 我深表歉意 如果您能提供任何帮助 我将不胜感激 Goal 在 Sheet1 中搜索关键字 活动 站点地址 描述 所有者 估价 子类型 和 DATE B 一旦找到关键
  • 如何使用 UITableViewCell 附件复选标记取消选中所有行

    我有一个UITableView每行包含一个复选框 使用UITableViewCellAccessoryCheckmark 我不知道如何使用取消选中所有复选框didSelectRowAtIndexPath method void tableV
  • 如何通过弹出窗口获取输入并通过 javascript/jquery 将文本放入变量中

    我的页面上有一个按钮 单击时 应出现一个弹出框 允许用户输入文本 当按下 确定 提交 时 我的 jscript 将使用输入的数据执行一些功能 非常简单 但我就是不知道该怎么做 Thanks 以最简单的形式 您可以使用提示 问题 默认 摘自w
  • 使用真正的随机盐或用户名盐加胡椒进行密码哈希?

    考虑以下两种方法 hashedPassword hash trulyRandomSalt password 其中 hashedPassword 和 trueRandomSalt 存储在数据库中 hashedPassword hash app
  • 无法连接到应用程序正在侦听的 Docker 容器端口

    我想运行 Jenkins 但为了演示问题 我在 Ubuntu 15 10 中运行 netcat 服务器容器 Docker version 1 6 2 build 7c8fca2 这是我的 Dockerfile FROM ubuntu CMD
  • 使用 pandas dataframe 的内存泄漏

    我在用pandas DataFrame在多线程代码中 实际上是DataFrame called Sound 我注意到我有内存泄漏 因为我的程序的内存使用量逐渐增加超过 1000 万 最终达到计算机内存的 100 并崩溃 I used obj
  • 在 dart 中使用 source_gen 为一系列已解析文件生成一个文件

    我有一个创建迷你反射系统所需的模型列表 我分析了可序列化包并了解如何为每个文件创建一个生成的文件 但是 我找不到如何为大量文件创建一个文件 那么 如何使用 source gen 为一系列文件动态生成一个文件呢 Example Files用户
  • 使会话无效

    我有一个基于 jsp servlet 的应用程序 会话时间超过 30 分钟 我想在有人有意或无意关闭浏览器窗口时立即使会话无效 操作系统关闭 从tast管理器关闭 断电 我可以对此进行检查并使会话无效吗 无法处理这种情况 有一些浏览器提供此
  • 在 JavaScript 中将“'”替换为“”

    我的字符串是这样的 temp SE019 SR132 SC123 我使用如下函数 temp replace 但结果将是 SE019 SR132 SC123 仅删除第一个引号 我需要删除所有引号 使用正则表达式文字g 对于全局 意味着匹配al
  • 无法导入设置;不在系统路径上

    我正在尝试让 Django 使用 virtualenv 工作 我已经上线了 hello world 页面 但是 现在似乎出了问题 因为我的大多数命令都给出了有关 myProject settings 的相同错误 myenv user min
  • 如何使用 Azure 表存储选择 RowKey 范围?

    我想使用主键查询我的天蓝色表存储 另外我想检查我的 RowKey 是否在一个范围内 例如范围 02001 到 02999 有人能告诉我该怎么做吗 我了解如何用简单的方法查询 PK where fooEntiy PartitionKey pa
  • 如何在Python中配置装饰器

    我正在尝试使用 Thespian https thespianpy com doc https thespianpy com doc 一个用于演员模型的 Python 库 特别是我正在尝试使用 剧团 功能 据我了解 剧团装饰器充当调度程序
  • 合并 GitHub 帐户 - 贡献和统计数据

    我想合并我的两个 GitHub 帐户 这意味着将存储库所有权转移到一个帐户 并删除另一个帐户 根据https help github com articles transferring a repository https help git
  • 新的时间轴,如按钮行为

    在新样式的页面选项卡上 赞 按钮不再刷新页面 这打破了 Like gates 的现有工作流程 即在服务器上检查签名的请求 就像页面一样 页面刷新 繁荣 选项卡现在更新为 喜欢 状态 当用户单击新的 赞 按钮时 是否会触发任何类型的事件 或者
  • 为什么 Mongoose 不验证空文档?

    假设我有一个非常简单的模式 带有一个始终返回 false 的自定义验证函数 var MofoSchema new mongoose Schema name String MofoSchema path name validate funct
  • 60 秒后阻止操作调用超时 - 如何访问结果?

    我正在尝试调用 Apache OpenWhisk 操作 使用 JavaScript SDK 作为远程函数 我想等待函数结果可在我的应用程序中使用 这通常通过使用阻塞调用来处理 例如 ow actions invoke name blocki
  • 多语言网站 - 如何设置所需的默认语言?

    我用 joomla 多语言制作网站 塞尔维亚语和英语 我正在使用 joomla 3 3 3 和 joomla 内置对多语言的支持 但我想将塞尔维亚语设置为默认语言 因此 当用户访问我的网站时 默认情况下总是使用塞尔维亚语 怎么做 谢谢 您必
  • 将日期添加到日期对象[重复]

    这个问题在这里已经有答案了 可能的重复 如何在今天的日期上添加天数 https stackoverflow com questions 3818193 how to add number of days to todays date 我很困
  • 安装 libCurl - ruby​​ 1.9.3 ..rails 3.2.12 ..Windows

    所以 我正在尝试让 feedzirra 启动并运行 ruby 1 9 3p448 Rails 3 2 12 我去了http curl haxx se download html Win32 http curl haxx se downloa
  • 如何使用内容解析器/提供者测试类?

    我正在尝试测试查询内容解析器的类 我想用MockContentResolver并嘲笑query方法 问题是这个方法是最终的 我应该怎么办 使用模拟框架 模拟其他类 提前致谢 public class CustomClass private