Now I know you can use reflection in Java to access private fields, but its a bit clunky. But recently I have been reading about Groovy, and found that it gives you full access to all your Java objects, but allows you to ignore private specifiers.
So as an example, say I have a counter class, one which allows users to get the next value of the counter, but cannot provide anyway of altering the counter for that would invalidate its purpose.
package net.usersource.example; import java.util.concurrent.atomic.AtomicInteger; public class Counter { private final AtomicInteger counter; public Counter() { counter = new AtomicInteger(0); } public int getNext() { return ensuringValueDoesNotRollIntoNegativeValues(counter.incrementAndGet()); } private int ensuringValueDoesNotRollIntoNegativeValues(int value) { if( value < 0 ) { if( counter.compareAndSet(value, 0) ) { return 0; } else { return getNext(); } } return value; } }Now, how do I test this without calling getNext() until it reaches Integer.MAX_VALUE? Do you know just how big MAX_VALUE really is, and how long that will take? Thats not really an option - so I need somehow to change the underlying counter.
Now I could do that with reflection, but I can do it much simpler using Groovy (which if you look closely, especially the way I have written it, looks like java) ...
package net.usersource.example import org.junit.Test; import org.junit.Assert; import java.lang.Integer; public class CounterTest { @Test public void verifyFirstObtainedCounterValueIsOne() { Counter c = new Counter(); Assert.assertEquals( c.getNext(), 1 ); } @Test public void verifyThatAtMaxIntTheNextValueIsZero() { Counter c = new Counter(); c.counter.set(Integer.MAX_VALUE-1); Assert.assertEquals( Integer.MAX_VALUE, c.getNext() ); Assert.assertEquals( 0, c.getNext() ); } }This was TDD'd so I only knew the solution thanks to the test.
Unfortunately I have found some issues with the Eclipse Groovy Plugin - its auto-completion is a bit zealous in someways (wants to try and match everything bringing your machine to a crawl) and ignorant in others (not matching in imports). Also the GUnit results were reporting exceptions the line above the line with the issue - which caused me some confusion initially, and I need to investigate that further.
But to me this is a neat way of testing Java code, by stepping out of Java to something that makes it easier, whilst staying on the JVM.
No comments:
Post a Comment