Testing WeakReference

What is the correct approach to testing weak links in Java?

My initial idea is to do the following:

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

The caveat I have about the approach uses System.gc (), as I understand that it can behave differently on different JVMs.

+6
source share
2 answers

There is no 100% bomb-proof way to test code using reference types. The behavior of Reference objects depends on when the GC is running, and there is no 100% reliable way to force the GC to start.

The best you can do is:

  • make sure you have the correct JVM parameters set when running the tests, and
  • write your test so that it does not fail if System.gc() is no-op OR who wants to disable or skip the test or ignore the test failure.

(You should be able to detect that System.gc() ignored by looking at how much memory is used before and after the call, for example by calling Runtime.totalMemory() )


Actually, there is one more "solution". Ask the unit test to create a huge amount of garbage ... enough to ensure that you turn on garbage collection. (Not a good idea, IMO.)

+5
source

A new answer to an old question; I found your question as I am dealing with the same problem: I want to write unit test to verify that my class under testing does something very specific if the WeakReference referent becomes zero.

First I wrote a simple test case that would set the referent to null; then call System.gc() ; and interestingly enough: at least in my eclipse, it was โ€œgood enoughโ€ for my weakRefernce.get() to return null.

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

So, after thinking a little 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 well too.

Meaning: The general answer to this problem is a factory that creates a WeakReference for objects for you. So, when you want to test your production code; you provide it with a factory; and that the factory will in turn mock WeakReference objects; and now you have complete control over the behavior of this weak reference object.

And โ€œfull controlโ€ is much better than assuming that the GC may do what you hope it does.

+3
source

Source: https://habr.com/ru/post/918849/


All Articles