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