2012-06-24 62 views
6

在Java中測試弱引用的正確方法是什麼?測試WeakReference

我最初的想法是做到以下幾點:

public class WeakReferenceTest { 

    public class Target{ 
     private String value;  

     public Target(String value){ 
      this.value = value; 
     }  
     public String toString(){ 
      return value; 
     } 
    } 

    public class UsesWeakReference{  
     WeakReference<Target> reference; 

     public UsesWeakReference(Target test){ 
      reference = new WeakReference<Target>(test); 
     }  
     public String call(){ 
      Target test = reference.get(); 
      if(test != null){ 
       return test.toString(); 
      } 
      return "empty"; 
     } 
    } 

    @Test 
    public void testWeakReference(){  
     Target target = new Target("42"); 

     UsesWeakReference usesWeakReference = new UsesWeakReference(target);  
     WeakReference<Target> triggerReference = new WeakReference<Target>(target);  
     assertEquals("42", usesWeakReference.call()); 

     target = null;  
     while(triggerReference.get() != null){ 
      System.gc(); 
     } 

     assertEquals("empty", usesWeakReference.call());  
    }  
} 

我對方法的預約使用System.gc()的,按照我的理解,它可以表現不同的不同的JVM。

回答

5

沒有100%的使用引用類型測試代碼的防爆方式。 Reference對象的行爲取決於GC運行的時間,並且沒有100%可靠的方式強制GC運行。

你能做的最好的是:

  • 檢查是否具有運行測試時設置正確的JVM選項,
  • 編寫測試,以便它不會在事件System.gc()失敗是無操作的願意禁用或跳過測試,或忽略測試失敗。

(你應該能夠檢測System.gc()正在看多少內存在使用前和呼叫後忽略;例如,通過調用Runtime.totalMemory()


其實,還有另一種「解」。讓你的單元測試產生大量垃圾......足以保證你將觸發垃圾收集。 (不是一個好主意,國際海事組織。)

+0

我很欣賞答案......驗證了我的觀點。 –

3

舊問題的新答案;我發現你的問題,因爲我正在處理完全相同的問題:我想寫一個單元測試,以驗證我的類在測試中做了非常具體的事情,如果WeakReference的參考變爲null。

我第一次寫了一個簡單的測試用例,將被引用對象設置爲null;然後致電System.gc();有趣的是:至少在我的日食中,這對我的weakRefernce.get()返回null是「足夠好」。

但誰知道這是否適用於未來幾年將運行此單元測試的未來環境。

所以,想些後:

@Test 
public void testDeregisterOnNullReferentWithMock() { 
    @SuppressWarnings("unchecked") 
    WeakReference<Object> weakReference = EasyMock.createStrictMock(WeakReference.class); 
    EasyMock.expect(weakReference.get()).andReturn(null); 
    EasyMock.replay(weakReference); 
    assertThat(weakReference.get(), nullValue()); 
    EasyMock.verify(weakReference); 
} 

工作得很好了。

含義:此問題的通用答案是爲您創建對象的WeakReference的工廠。所以,當你想測試你的產品代碼時,你提供一個嘲弄的工廠;而這家工廠將依次嘲笑WeakReference對象;現在你完全可以控制那個弱參考對象的行爲。

而「完全控制」比好得多,假設 GC可能做你希望它做的事情。

+0

嘲笑在這裏最好,因爲GC不是完全確定性的,也不是可控的。 – kerner1000

+0

非常正確 - 我添加了另一個段落以使其更加清晰。爲了記錄:還有什麼我可以做的,使這個upvote值得在你的眼中? – GhostCat

+0

我認爲這已經很清楚了。我不得不爲我的類型創建另一個構造函數,我想測試它以提供一個模擬的WeakReference(是一個主要用於測試乾淨代碼的構造函數?))。也許值得注意的是,嘲笑WeakReference對於重現性測試來說是最好的,但是不太「現實」,這意味着如果你想明確測試不可靠的GC行爲,這可能不是最好的方法。 (感謝upvote;)) – kerner1000