
- •brief contents
- •contents
- •foreword
- •preface
- •acknowledgments
- •about this book
- •Roadmap
- •Code conventions and downloads
- •Author Online
- •About the author
- •about the cover illustration
- •1 Why add Groovy to Java?
- •1.1 Issues with Java
- •1.1.1 Is static typing a bug or a feature?
- •1.1.2 Methods must be in a class, even if you don’t need or want one
- •1.1.3 Java is overly verbose
- •1.1.4 Groovy makes testing Java much easier
- •1.1.5 Groovy tools simplify your build
- •1.2 Groovy features that help Java
- •1.3 Java use cases and how Groovy helps
- •1.3.1 Spring framework support for Groovy
- •1.3.2 Simplified database access
- •1.3.3 Building and accessing web services
- •1.3.4 Web application enhancements
- •1.4 Summary
- •2 Groovy by example
- •2.1 Hello, Groovy
- •2.2 Accessing Google Chart Tools
- •2.2.1 Assembling the URL with query string
- •2.2.2 Transmitting the URL
- •2.2.3 Creating a UI with SwingBuilder
- •2.3 Groovy Baseball
- •2.3.1 Database data and Plain Old Groovy Objects
- •2.3.2 Parsing XML
- •2.3.3 HTML builders and groovlets
- •2.4 Summary
- •3 Code-level integration
- •3.1 Integrating Java with other languages
- •3.2 Executing Groovy scripts from Java
- •3.2.1 Using JSR223 scripting for the Java Platform API
- •3.2.2 Working with the Groovy Eval class
- •3.2.3 Working with the GroovyShell class
- •3.2.4 Calling Groovy from Java the easy way
- •3.2.5 Calling Java from Groovy
- •3.3 Summary
- •4 Using Groovy features in Java
- •4.1 Treating POJOs like POGOs
- •4.2 Implementing operator overloading in Java
- •4.3 Making Java library classes better: the Groovy JDK
- •4.4 Cool AST transformations
- •4.4.1 Delegating to contained objects
- •4.4.2 Creating immutable objects
- •4.4.3 Creating singletons
- •4.5 Working with XML
- •4.6 Working with JSON data
- •4.7 Summary
- •5 Build processes
- •5.1 The build challenge
- •5.2 The Java approach, part 1: Ant
- •5.3 Making Ant Groovy
- •5.3.1 The <groovy> Ant task
- •5.3.2 The <groovyc> Ant task
- •5.3.3 Writing your build in Groovy with AntBuilder
- •5.3.4 Custom build scripts with Gant
- •5.3.5 Ant summary
- •5.4 The Java approach, part 2: Maven
- •5.4.2 The GMaven project
- •5.4.3 Maven summary
- •5.5 Grapes and @Grab
- •5.6 The Gradle build system
- •5.6.1 Basic Gradle builds
- •5.6.2 Interesting configurations
- •5.7 Summary
- •6 Testing Groovy and Java projects
- •6.1 Working with JUnit
- •6.1.1 A Java test for the Groovy implementation
- •6.1.2 A Groovy test for the Java implementation
- •6.1.3 A GroovyTestCase test for a Java implementation
- •6.2 Testing scripts written in Groovy
- •6.2.1 Useful subclasses of GroovyTestCase: GroovyShellTestCase
- •6.2.2 Useful subclasses of GroovyTestCase: GroovyLogTestCase
- •6.3 Testing classes in isolation
- •6.3.1 Coerced closures
- •6.3.2 The Expando class
- •6.3.3 StubFor and MockFor
- •6.4 The future of testing: Spock
- •6.4.1 The Search for Spock
- •6.4.2 Test well, and prosper
- •6.4.4 The trouble with tribbles
- •6.4.5 Other Spock capabilities
- •6.5 Summary
- •7 The Spring framework
- •7.1 A Spring application
- •7.2 Refreshable beans
- •7.3 Spring AOP with Groovy beans
- •7.4 Inline scripted beans
- •7.5 Groovy with JavaConfig
- •7.6 Building beans with the Grails BeanBuilder
- •7.7 Summary
- •8 Database access
- •8.1 The Java approach, part 1: JDBC
- •8.2 The Groovy approach, part 1: groovy.sql.Sql
- •8.3 The Java approach, part 2: Hibernate and JPA
- •8.4 The Groovy approach, part 2: Groovy and GORM
- •8.4.1 Groovy simplifications
- •8.5 Groovy and NoSQL databases
- •8.5.1 Populating Groovy vampires
- •8.5.2 Querying and mapping MongoDB data
- •8.6 Summary
- •9 RESTful web services
- •9.1 The REST architecture
- •9.3 Implementing JAX-RS with Groovy
- •9.4 RESTful Clients
- •9.5 Hypermedia
- •9.5.1 A simple example: Rotten Tomatoes
- •9.5.2 Adding transitional links
- •9.5.3 Adding structural links
- •9.5.4 Using a JsonBuilder to control the output
- •9.6 Other Groovy approaches
- •9.6.1 Groovlets
- •9.6.2 Ratpack
- •9.6.3 Grails and REST
- •9.7 Summary
- •10 Building and testing web applications
- •10.1 Groovy servlets and ServletCategory
- •10.2 Easy server-side development with groovlets
- •10.2.1 A “Hello, World!” groovlet
- •10.2.2 Implicit variables in groovlets
- •10.3.2 Integration testing with Gradle
- •10.3.3 Automating Jetty in the Gradle build
- •10.4 Grails: the Groovy “killer app”
- •10.4.1 The quest for the holy Grails
- •10.5 Summary
- •A.1 Installing a JDK
- •A.2 Installing Groovy
- •A.3 Testing your installation
- •A.4 IDE support
- •A.5 Installing other projects in the Groovy ecosystem
- •B.1 Scripts and the traditional example
- •B.2 Variables, numbers, and strings
- •B.2.1 Numbers
- •B.2.2 Strings and Groovy strings
- •B.3 Plain Old Groovy Objects
- •B.4 Collections
- •B.4.1 Ranges
- •B.4.2 Lists
- •B.4.3 Maps
- •B.5 Closures
- •B.6 Loops and conditionals
- •B.6.1 Loops
- •B.6.2 Conditionals
- •B.6.3 Elvis
- •B.6.4 Safe de-reference
- •B.7 File I/O
- •B.8.1 Parsing and slurping XML
- •B.8.2 Generating XML
- •B.8.3 Validation
- •B.9 JSON support
- •B.9.1 Slurping JSON
- •B.9.2 Building JSON
- •index
- •Symbols

128 CHAPTER 6 Testing Groovy and Java projects
GroovyTestCase. From there I’ll discuss testing classes in isolation using mocks and stubs. This involves the built-in mock and stub capabilities in Groovy, both through the Expando class and through Groovy’s MockFor and StubFor classes. Finally I’ll show you a glimpse of the future in the form of the powerful Spock framework, a pure Groovy library that simplifies testing for both Java and Groovy projects.
Figure 6.1 is a guide to the technologies discussed in this chapter.
6.1Working with JUnit
The agile development community created JUnit (http://junit.org) as a great tool for automating tests. While other Java testing tools exist, JUnit has been so influential that nearly every Java developer I encounter has either used it or heard of it. JUnit’s success has spawned an entire family of comparable tools for other languages (known collectively as “xUnit”). JUnit is simple, easy to use, and ubiquitous in the Java world. As I’ll show in this chapter, the available Groovy tools also are easy to use and easy to learn, and some of them are based directly on JUnit. 1
Adding JUnit to your projects (a review from chapter 5)
JUnit is an open source project created by two of the founders of Extreme Programming,1 Erich Gamma and Kent Beck. The JUnit library can be downloaded from the home site (http://junit.org), but it’s built into most of the common IDEs, including Eclipse, NetBeans, and IntelliJ IDEA. It also can be retrieved from the Maven central repository, using a POM dependency of the form
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
As an alternative, JUnit version 4.5 and above enables the artifact ID junit-dep instead, which does not include the so-called Hamcrest matchers (http://code
.google.com/p/hamcrest/) that simplify the syntax in certain cases. Like most cool projects, the source code for JUnit now resides at GitHub, at https://github.com/ junit-team/junit.
Most of the Gradle build files in this book (especially for the projects in this chapter) include JUnit as a “test-compile” dependency. That means classes in the API (like org.junit.TestCase and org.junit.Assert) are only available for test classes.
When writing JUnit tests in Groovy, you have two options. You can write a JUnit test with annotations as usual, but implement it in Groovy, or you can extend the
1Now known more commonly as “agile” development, because most Fortune 500 companies don’t want to be associated with “extreme” anything.
www.it-ebooks.info

Working with JUnit |
129 |
GroovyTestCase class. The only difference is that GroovyTestCase adds a few additional methods to the TestCase class from JUnit.
Because this book is all about integration, I’d like to examine the following cases:
■Use a standard Groovy JUnit test to check a Java implementation.
■Use a standard Java JUnit test to check a Groovy implementation.
■Write a Groovy test that extends GroovyTestCase to see what additions it provides.
In each case I need something to test. Because I plan to mix the languages, one way I’ve found that makes that easier is to declare my methods in a Java interface and then implement it in both languages. That’s actually a pretty general rule.
GROOVY IMPLEMENTS JAVA Groovy classes can implement Java interfaces as easily as Java classes can.
The next listing shows a Java interface, called UtilityMethods, containing three method declarations.
Listing 6.1 A Java interface with three methods
public interface UtilityMethods { int[] getPositives(int... values); boolean isPrime(int x);
boolean isPalindrome(String s);
}
In true test-driven development (TDD) I would now write the tests, watch them fail, and then write the correct implementations. Because the subject of this chapter is the tests rather than the implementations, let me present the implementations first.2
The following listing is the Java implementation of the UtilityMethods interface.
Listing 6.2 The Java implementation of the UtilityMethods interface
import java.util.ArrayList; import java.util.List;
public class JavaUtilityMethods implements UtilityMethods {
public int[] getPositives(int... values) { List<Integer> results = new ArrayList<Integer>(); for (Integer i : values) {
if (i > 0) results.add(i);
}
int[] answer = new int[results.size()]; for (int i = 0; i < results.size(); i++) {
answer[i] = results.get(i);
}
2I try to use TDD, but more often I use GDD, which stands for Guilt-Driven Development. If I write code and it’s not tested, I feel guilty and write a test for it.
www.it-ebooks.info

130 CHAPTER 6 Testing Groovy and Java projects
return answer;
}
public boolean isPrime(int x) {
if (x < 0) throw new IllegalArgumentException("argument must be > 0");
if (x == 2) return true;
for (int i = 2; i < Math.sqrt(x) + 1; i++) { if (x % i == 0) return false;
}
return true;
}
public boolean isPalindrome(String s) { StringBuilder sb = new StringBuilder(); for (char c : s.toCharArray()) {
if (Character.isLetter(c)) { sb.append(c);
}
}
String forward = sb.toString().toLowerCase();
String backward = sb.reverse().toString().toLowerCase(); return forward.equals(backward);
}
}
The implementations will not be surprising to anyone with a Java background. The Groovy implementation, shown in the next listing, is somewhat shorter.
Listing 6.3 The Groovy implementation of the UtilityMethods interface
class GroovyUtilityMethods implements UtilityMethods {
A range with an open upper bound
@Override |
|
|
int[] getPositives(int... values) { |
|
|
values.findAll { it > 0 } |
findAll returns all values |
|
} |
||
satisfying the closure |
@Override
boolean isPrime(int x) {
if (x < 0) throw new IllegalArgumentException('argument must be > 0') if (x == 2) return true
(2..< Math.sqrt(x) + 1).each { num ->
if (x % num == 0) return false // DANGER! THIS IS A BUG!
}
return true
}
@Override
boolean isPalindrome(String s) {
|
String str = s.toLowerCase().replaceAll(/\W/,'') |
||
} |
str.reverse() == str |
|
The Groovy JDK adds a |
|
|
||
} |
|
|
reverse method to String |
www.it-ebooks.info

Working with JUnit |
131 |
There is, in fact, a subtle bug in the implementation of the isPrime method. The tests will detect it and give me a chance to explain the trap.
In the next subsection I’ll use Java to test the Groovy implementation and fix the bug. Then I’ll use Groovy to test the Java implementation, and finally I’ll write the test as a subclass of GroovyTestCase to see how that can help.
6.1.1A Java test for the Groovy implementation
The following listing contains a JUnit 4 test, written in Java, to test the Groovy implementation. It includes a static import for the methods in the org.junit.Assert class and @Test annotations for the individual tests.
Listing 6.4 A Java JUnit test to check the Groovy implementation
package mjg;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue;
import java.util.ArrayList; import java.util.List;
import org.junit.Test;
Static import so assert methods don’t start with Assert
public class GroovyImplJavaTest {
private UtilityMethods impl = new GroovyUtilityMethods();
@Test
public void testGetPositives() {
int[] testValues = {-3, 1, 4, -1, 5, -2, 6}; List<Integer> testList = new ArrayList<Integer>(); testList.add(1); testList.add(4); testList.add(5); testList.add(6);
int[] results = impl.getPositives(testValues); for (int i : results) {
assertTrue(testList.contains(i));
}
}
Results in List in order to use contains method
@Test
public void testIsPrime() {
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; for (int p : primes) {
assertTrue(impl.isPrime(p));
}
assertFalse("9 is not prime", impl.isPrime(9));
} |
|
|
|
@Test(expected=IllegalArgumentException.class) |
|
Test passes if |
|
public void testNegativePrime() { |
|||
exception thrown |
|||
impl.isPrime(-3); |
|
||
} |
|
|
www.it-ebooks.info

132 |
CHAPTER 6 Testing Groovy and Java projects |
@Test
public void testIsPalindrome() { assertTrue(impl.isPalindrome("Step on no pets!")); assertTrue(impl.isPalindrome("Lisa Bonet ate no basil")); assertTrue(impl.isPalindrome(
"Are we not drawn onward, we few, drawn onward to new era!")); assertFalse(impl.isPalindrome("This is not a palindrome"));
}
}
In JUnit 3 tests extended the org.junit.TestCase class, and test methods were detected by reflection. TestCase had all the needed assert methods in it. Now, in JUnit 4, tests don’t have a superclass and are detected through the @Test annotation. The assert methods are now static methods in the Assert class, leading to probably the most common use of static imports in all of Java. If you do a static import on the Assert class you can write the assert methods the same way they looked in the older version.
The only other interesting part of this is the use of the expected property of the @Test annotation, which declares that the test only passes if the expected exception is thrown. Figure 6.2 shows the result.
The test detected that the Groovy implementation is returning true for all cases. The Groovy implementation divides the given number by all the integers from 2 up to the square root of the number minus 1, looking for any that come out even. That
Figure 6.2 The isPrime method has a bug, but the rest are fine.
www.it-ebooks.info