测试WeakReference

Joh*_*sen 8 java unit-testing weak-references

在Java中测试弱引用的正确方法是什么?

我最初的想法是做以下事情:

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());    
    }    
}
Run Code Online (Sandbox Code Playgroud)

我对该方法的保留是使用System.gc(),因为我知道它在不同的JVM上的行为可能不同.

Ste*_*n C 5

没有100%防弹方式来测试使用Reference类型的代码.Reference对象的行为取决于GC运行的时间,并且没有100%可靠的方法来强制GC运行.

你能做的最好的事情是:

  • 检查运行测试时是否设置了正确的JVM选项,以及
  • 编写测试,以便在System.gc()无操作不愿意禁用或跳过测试或忽略测试失败的情况下不会失败.

(您应该能够System.gc()通过查看呼叫前后使用的内存量来检测是否被忽略;例如通​​过调用Runtime.totalMemory())


实际上,还有另一种"解决方案".让您的单元测试产生大量垃圾......足以保证您将触发垃圾收集.(不是一个好主意,IMO.)


Gho*_*ica 5

旧问题的新答案;我在处理完全相同的问题时发现了您的问题:我想编写一个单元测试,以验证我的被测类在 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);
}
Run Code Online (Sandbox Code Playgroud)

也很好用。

意思是:这个问题的通用答案是一个为你创建对象的 WeakReference 的工厂。所以,当你想测试你的生产代码时;你为它提供了一个模拟工厂;该工厂将依次模拟 WeakReference 对象;现在您可以完全控制该弱引用对象的行为。

并且“完全控制”比假设GC 可能会做您希望它正在做的事情要好得多。