2015-09-25 34 views
2

隨意改善標題在這種特殊情況下,我有點不創新。單元測試:NoSuchMethodError調用時Notification.setLatestEventInfo()

我正在執行一個單元測試來檢查通知,這幾乎不可能我知道,但我想檢查我可以自動化多遠。

我無法測試的代碼這個簡單的行:

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); 
    [...] 

我得到這個異常:

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) 

不難猜測,谷歌人來電來訪,除去的方法(或者更恰當在Android Marshmallow SDK中用@hide註解)。我已經驗證了這個調用缺少最新的文檔,但它是在API 1 AFIK中引入的。

我該如何解決這個問題?

事情我試圖和被困:

  • 重寫回調,並嘲笑這種方法,而不必調用該呼叫:
    我得到了它設法獲取Class<?>有回調,但與方法,我可以重寫一個洞方法?我的意思是我需要修補它,我不能嘲笑它。
  • 注入該呼叫,但如何?我可以重寫它,而不是添加它。
  • 抑制與呼叫:

    PowerMockito.spy(Notification.class); 
    PowerMockito.suppress(PowerMockito.method(Notification.class, "setLatestEventInfo", Context.class, CharSequence.class, CharSequence.class, PendingIntent.class)); 
    

    不行的醚,因爲我嘗試踢不存在的方法。

  • 更改此測試的目標SDK,但我該怎麼做?

回答

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); 
}