单元测试:调用Notification.setLatestEventInfo()时出现NoSuchMethodError

时间:2015-09-25 10:12:00

标签: android unit-testing mockito powermock

  

随意改善标题我在这种特殊情况下有点无创意。

我正在实施检查通知的单元测试,我知道这几乎不可能,但我想检查一下我可以自动化多远。

我无法测试这段简单的代码:

Couldn't find any files, check your path! on line 27 in file openFiles.c. Check was filesFound > 0, value was 0

原因之一是愚蠢而简单。这里的代码将在内部执行:

Notification test = new NotificationCompat.Builder(context).build();

我得到了这个例外:

public Notification build(Builder b, BuilderExtender extender) {
    Notification result = b.mNotification;
    result.setLatestEventInfo(b.mContext, b.mContentTitle,
            b.mContentText, b.mContentIntent);
    [...]

不难猜测,Google员工在这里称之为Android Marshmallow SDK中已删除(或使用Caused by: java.lang.NoSuchMethodError: android.app.Notification.setLatestEventInfo(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Landroid/app/PendingIntent;)V at android.support.v4.app.NotificationCompat$NotificationCompatImplBase.build(NotificationCompat.java:479) at android.support.v4.app.NotificationCompat$Builder.build(NotificationCompat.java:1561) 更正确注释)的方法。我已经验证了呼叫缺少最新的文档,但它是在API 1 AFIK中引入的。

我该如何解决这个问题?

我尝试过的事情被困住了:

  • 覆盖回调,并在不调用该调用的情况下模拟该方法:
    我让它设法通过回调得到@hide,但是我可以用哪种方法覆盖一个孔方法?我的意思是我需要修补它,我不能只是嘲笑它。
  • 注入该电话,但如何?我可以覆盖它而不是添加它。
  • 使用以下方法取消呼叫:

    Class<?>

    因为我试图踢出一个不存在的方法,所以不能工作。

  • 更改此测试的目标SDK,但我该怎么办?

1 个答案:

答案 0 :(得分:3)

解决方案比预期的要容易。我错过了默认情况下Build.VERSION.SDK_INT的值为0,因为它无法读取实际值。因此,支持库仅在存在此方法的平台上调用它。

this answer的帮助下。我只需添加此代码:

setFinalStatic(Build.VERSION.class.getDeclaredField("SDK_INT"), 23);

我的代码有效 好吧它仍然在其他地方崩溃,但通知已创建。 Wohoo!

实际功能:

public static void setFinalStatic(Field field, Object newValue) throws IllegalAccessException, NoSuchFieldException
{
    field.setAccessible(true);
    // remove final modifier from field
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}