UiAutomation injectInputEvent注入屏幕点击事件

参考链接


How to inject click event with Android UiAutomation.injectInputEvent

Jdk 6260652 Bug

最近在看JDK的源码:CopyOnWriteArrayList.javaArrayList.java,这2个类的构造函数,注释中有一句话看不懂。

上网查了一下资料,才知道see 6260652 这个编号代表JDK bug库中的编号。可以去官网查看bug详情

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6260652

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6515694

6260652 和6515694这2个bug,貌似是同一个问题。这个bug是什么意思呢?我们先来看看一些测试代码: 

 1、关于test1()

        SubClass 继承自BaseClass,由于SubClass数组中每一个元素都是SubClass对象,所以

这种强制类型转换不会报错。这其实就是java对象的向上转型,子类数组转换成父类数组是允许的。但是由于数组中元素类型都是SubClass类型的,所以

会报错

这也就是说假如我们有1个Object[]数组,并不代表着我们可以将Object对象存进去,这取决于数组中元素实际的类型。

2、关于test2()

需要注意,可以知道返回的实际类型是

而不是

我们调用

返回是String[]数组,所以我们不能将Object对象,放到objArray数组中。

3、关于test3()

ArrayList对象的toArray()返回就是Object[]数组,所以我们可以将任意对象存放到返回的Object[]数组中。

通过test2和test3可以看出,如果我们有1个

对象,当我么调用

的时候,objectArray 并不一定能够放置Object对象。这就是源码中的注释:

为了考虑这种情况,所以源码中进行了if判断,来防止错误的数组对象导致异常。

这个方法就是用来创建1个Object[]数组,这样数组中就可以存放任意对象了。

参考链接


Jdk 6260652 Bug

Android跳转权限设置页面

最近项目上有个需求,读取通讯录。当用户点了拒绝访问通讯录或者其他权限,导致无法使用,这时候我想重新打开权限设置,但是对于很多小白用户不知道怎么设置,这就会导致用户体验不友好的一面。

之前已经有人写过类似的文章,不过都比较分散,经实测将这些方法总结了一下。

要跳转的权限设置界面如图:目前手上只有华为和小米作为测试

继续阅读Android跳转权限设置页面

国产手机Android R(Android 11)系统执行Espresso UI(AndroidX)遇到的问题总结

最近在 Android R(Android 11)系统上执行以前写的Espresso UI(AndroidX)单元测试用例的时候,发现在 联想拯救者电竞手机Pro(128GB) 系统版本 12.5.225上,如果测试用例申请了通讯录写入权限,如下:

那么测试用例执行的时候,会报告如下错误:

详细的logcat日志如下:

目前测试发现,即使通过GrantPermissionRule授予权限,也是没用的,代码根本来不及执行,应用就一下被系统杀死了。

目前只能是不测试这部分功能。

OPPO/VIVO/小米等手机上,需要手工开启 后台弹出界面权限 才能执行单元测试。有个思路是通过UI Automator来自动开启这个权限,暂时还需要测试一下。

参考链接


Android R(11) ContentResolver报错java.lang.IllegalArgumentException: Invalid token limit

Android 11执行如下代码:

会出现如下错误:

原因为 Android 11 上使用 ContentResolver 的时候,已经不允许进行 SQL语句拼接,主要是为了防止 SQL注入攻击。

代码参考如下:

参考链接


limiting number of rows in a ContentResolver.query() function

Robolectric/PowerMock测试AIDL相关类

在编写单元测试用例的时候,如果被测试类是与AIDL相关的类,不管是直接调用,还是被测试类继承了AIDL生成的类,由于AIDL类是在编译期间动态生成的,并且每次构建都会重新生成一次(类名相同,但是Hash可能会变,文件修改日期必然变更)。

然而,由于PowerMock调用Objenesis库为了加快编译速度,会缓存同名的类,这样导致在运行时进行类型转换的时候无法通过校验,报告如下错误:

解决方法就是阻止Objenesis的缓存功能。在测试用例的根目录下新建文件,如下:

参考链接


Robolectric 3.8/PowerMock无法Mock由Executors线程运行的类

参照 Android Studio 3.6.3/4.0/4.1/4.2配置Robolectric-3.8/4.3.1/4.5.1/4.6.1 Powermock-1.6.6单元测试环境 进行单元测试,不过,由于工程的限制(不能依赖 AndroidX),我们只能在 Robolectric 3.8

Android Studio 4.1.3,JDK使用 Java 1.8

在执行如下测试用例的时候,发现当被测试代码使用 Executors 在子线程执行的时候,如果使用 PowermockWhenNew 对被测试对象进行仿真的时候,无法正确的被 Mock

被测试代码如下:

单元测试代码如下:

上述的测试代码在执行的时候,完全不会生效。

网上查询了一下,根据 Unable to get mocked instance of Executor in separate class 的介绍,我们需要在测试用例里面的@PrepareForTest里面增加 Executors.class,于是修改测试用例为如下:

结果出现一个诡异的现象,如果在创建对象的地方设置断点进行调试跟踪,就是正确的,去掉断点,就会失败。

这个问题卡住很久,结果突然想起以前写的一个差不多功能的被测试类,是能正常工作的,于是进行了代码对比,结果发现一个奇怪的现象,只要内部定义一个类来中继一下,就可以完美解决问题。于是修改被测试类,代码如下:

也就是内部定义来一个代理子类,初始化的时候,通过内部子类进行初始化。

这个现象比较奇怪,目前能解决问题,具体原因还是不详。

参考链接