Gradle is easy: Groovy tests

Today in Unit Testing, an evil framework class hid my important return value away in a private field.

Groovy to the rescue!

So far, all our code and tests are in Java. It took only two lines in build.gradle, as specified in the gradle documentation, and poof.

I put my little test class in src/test/groovy/package/structure, typed “gradle build” and wa-la! The results from the groovy test show up right along with the Java tests. Sweet.


class SomethingTest {
def email = "blah@blha.com";

UsefulClass usefulClass
CheckEmail subject

@Before
void setup() {
usefulClass = mock(UsefulClass.class);
subject = new Something(userService);
subject.setEmailAddress(email);
}

@Test
void falseWhenEmailFound() {
when(usefulClass.find(email)).thenReturn(new Thingie());

Reply result = subject.methodUnderTest();

assertEquals result.entity , Boolean.FALSE // see? that mean old private field is right there for the testing.
}

Lifting the blankets of Gradle

Gradle, the build system, is a DSL on top of Groovy. The build scripts (which are really configuration scripts) are Groovy code. So why do they look so weird?

Today I configured a particular obscure property of the eclipse plugin in milestone 6 of Gradle. The answer looks like:


apply plugin: 'eclipse-wtp'

eclipse {
wtp {
facet {
file {
whenMerged { config ->
config.facets.each {
if (it.name == 'jst.web') {
it.version = 3.0
}
}
config.facets.unique()
}
}
}
}
}

What is it doing? What is that “eclipse” word anyway? Is it a type? a variable? No — it is a method. The eclipse method (defined on the Project, but I’m not sure how) accepts a closure. Similarly, “wtp” is a method on EclipseModel, which accepts a closure. “facet” is a method on EclipseWtp.

But wait, how within the closure passed to the “wtp” method do we have access to a method on EclipseWtp? What determines that? The answer is: before calling our closure, Gradle sets some properties on the groovy.lang.Closure. The following snippet is modified for clarity from org.gradle.util.ConfigureUtil:


Closure copy = (Closure) configureClosure.clone();
copy.setResolveStrategy(Closure.DELEGATE_FIRST);
copy.setDelegate(delegate);
copy.call()

… where the delegate was passed in like so, in org.gradle.plugins.ide.eclipse.model.EclipseModel:


EclipseWtp wtp = new EclipseWtp()

void wtp(Closure closure) {
ConfigureUtil.configure(closure, wtp)
}

What happens is:
– wtp is a method that accepts our closure
– the wtp method sets an object of type EclipseWtp as the delegate on the closure
– the wtp method tells the closure to resolve methods on the delegate first.
– finally, the closure is called.

So, the strange scoping blocks in gradle turn out to be method calls. The way to find out what delegate you’re getting access to within each of these is to look at the DSL Reference or (for the real nitty-gritty details) the source code. For instance, the DSL Reference documentation for EclipseModel says that within the wtp {} block, you should see the documentation for EclipseWtp. (Note that the javadocs are useless. This is groovy trickery, not Java.)

This concept of a resolve strategy within a closure is interesting.