Testing WeakReference

There's no 100% bombproof way of testing code that uses the Reference types. The behaviour of Reference objects depends on when the GC runs, and there is no 100% reliable way of forcing the GC to run.

The best you can do is:

  • check that you have the right JVM options set when running the tests, and
  • write your test so that it doesn't fail in the event that System.gc() is a no-op OR be willing to disable or skip the test, or ignore the test failure.

(You should be able to detect that System.gc() is being ignored by looking at how much memory is in use before and after the call; e.g. by calling Runtime.totalMemory())


Actually, there is another "solution". Have your unit test generate a huge amount of garbage ... enough to guarantee that you will trigger garbage collection. (Not a good idea, IMO.)


New answer to old question; I found your question as I am dealing with the exact same problem: I want to write a unit test in order to verify that my class under test does something very specific if the referent of a WeakReference turns null.

I first wrote a simple test case that would set the referent to null; to then call System.gc(); and interestingly enough: at least within my eclipse, that was "good enough" for my weakRefernce.get() to return null.

But who knows if that will work for all the future environments that will run this unit test for the years to come.

So, after thinking some more:

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

Works nicely, too.

Meaning: the generic answer to this problem is a factory that creates WeakReference for objects for you. So, when you want to test your production code; you provide a mocked factory to it; and that factory will in turn mocked WeakReference objects; and now you are in full control regarding the behavior of that weak reference object.

And "full control" is much better than assuming that the GC maybe does what you hope it is doing.