2012-06-24 30 views
6

Cách tiếp cận thích hợp để kiểm tra một tham chiếu yếu trong Java là gì?Testing WeakReference

ý tưởng ban đầu của tôi là phải làm như sau:

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

Các phòng tôi có khoảng cách tiếp cận được sử dụng System.gc(), như tôi hiểu rằng nó có thể cư xử khác nhau trên JVM khác nhau.

Trả lời

5

Không có cách kiểm tra chống bom 100% sử dụng loại Tham chiếu. Hành vi của các đối tượng tham chiếu phụ thuộc vào thời điểm GC chạy, và không có cách nào đáng tin cậy 100% để buộc GC chạy.

Điều tốt nhất bạn có thể làm là:

  • kiểm tra rằng bạn có các tùy chọn JVM đúng thiết lập khi chạy các bài kiểm tra, và
  • viết thử nghiệm của bạn để nó không thất bại trong trường hợp System.gc() là số HOẶC không sẵn sàng để vô hiệu hóa hoặc bỏ qua thử nghiệm hoặc bỏ qua lỗi kiểm tra.

(Bạn sẽ có thể phát hiện rằng System.gc() đang được bỏ qua bằng cách nhìn vào bao nhiêu bộ nhớ được sử dụng trước và sau khi cuộc gọi; ví dụ như bằng cách gọi Runtime.totalMemory())


Trên thực tế, có một "dung dịch". Kiểm tra đơn vị của bạn tạo ra một lượng rác lớn ... đủ để đảm bảo rằng bạn sẽ kích hoạt bộ sưu tập rác. (Không phải là ý tưởng hay, IMO.)

+0

Tôi đánh giá cao câu trả lời ... xác nhận quan điểm của tôi. –

3

Câu trả lời mới cho câu hỏi cũ; Tôi tìm thấy câu hỏi của bạn khi tôi đang đối phó với cùng một vấn đề: Tôi muốn viết một bài kiểm tra đơn vị để xác minh rằng lớp của tôi đang được kiểm tra thực hiện điều gì đó rất cụ thể nếu tham chiếu của một WeakReference biến null.

Lần đầu tiên tôi viết một trường hợp thử nghiệm đơn giản sẽ đặt tham chiếu thành null; sau đó gọi System.gc(); và đủ thú vị: ít nhất là trong nhật thực của tôi, đó là "đủ tốt" cho số weakRefernce.get() của tôi để trả về giá trị rỗng.

Nhưng ai biết liệu điều đó có hiệu quả với tất cả các môi trường trong tương lai sẽ chạy thử nghiệm đơn vị này trong những năm tới không.

Vì vậy, sau khi suy nghĩ một số chi tiết:

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

Tác phẩm độc đáo, quá.

Ý nghĩa: câu trả lời chung cho vấn đề này là một nhà máy tạo ra WeakReference cho các đối tượng cho bạn. Vì vậy, khi bạn muốn kiểm tra mã sản xuất của mình; bạn cung cấp một nhà máy chế nhạo cho nó; và nhà máy đó sẽ lần lượt chế nhạo các đối tượng WeakReference; và bây giờ bạn có toàn quyền kiểm soát hành vi của đối tượng tham chiếu yếu đó.

Và "kiểm soát hoàn toàn" tốt hơn nhiều so với giả định rằng GC có thể làm những gì bạn hy vọng nó đang làm.

+0

Mocking là tốt nhất ở đây, như GC không phải là hoàn toàn xác định cũng không thể kiểm soát. – kerner1000

+0

Rất chính xác - tôi đã thêm một đoạn văn khác để làm rõ hơn.Đối với các hồ sơ: có bất cứ điều gì khác tôi có thể làm để làm cho upvote này xứng đáng trong mắt của bạn? – GhostCat

+0

Tôi nghĩ rằng nó đã được khá rõ ràng. Tôi đã phải tạo một hàm tạo khác cho kiểu của tôi mà tôi muốn kiểm tra để cung cấp một WeakReference giả lập (là một hàm tạo chủ yếu để thử nghiệm mã sạch?))). Có lẽ điều đáng lưu ý là việc chế nhạo WeakReference là tốt nhất cho các bài kiểm tra có thể tái sản xuất nhưng ít "thực tế" hơn, có nghĩa là nếu bạn muốn kiểm tra rõ ràng hành vi GC không đáng tin cậy thì có lẽ đó không phải là cách tiếp cận tốt nhất. (cảm ơn cho upvote;)) – kerner1000