What Groovy auto-imports

Alonso Del Arte
3 min readJul 31, 2023

--

Photo by Stefan Cosma on Unsplash

I had heard of the Spock testing framework before, I knew IntelliJ IDEA (even the Community Edition) has Spock. Or, more precisely, IntelliJ can have Maven download it and add it to the XML file with the dependencies.

So I decided to give Spock a try. I made a Hello World in Java, just to have something simple to test.

package org.example;

public class HelloWorld {

// TODO: Write tests for this
public static void main(String[] args) {
System.out.println("World, hello?");
}

}

That should fail the test. I told IntelliJ to make a test class using the Spock framework. Much to my surprise, it made the test class not in Java but in Groovy, a programming language that I had heard of before but had never programmed in.

After a little fumbling around, I wrote my first Spock test based on an example I found in a Google search. The following is a little cleaned up from my first draft.

My first draft was about what you’d expect from a Java programmer writing Groovy for the first time. My friend Mark helped me make it more idiomatic for Groovy, but I have purposely left three warnings from my first draft in the following version:

package org.example

import java.io.ByteArrayOutputStream // Warning, unused import?
import java.io.OutputStream // Warning, unused import?
import java.io.PrintStream // Warning, unused import?

import spock.lang.Specification

class HelloWorldTest extends Specification {

def "Hello World should say Hello World"() {
given:
def expected = "Hello, world!"
when:
def usualOut = System.out // originally had type declared
def interceptor = new ByteArrayOutputStream()
def tempOut = new PrintStream(interceptor)
System.setOut(tempOut)
HelloWorld.main()
System.setOut(usualOut)
def actual = interceptor.toString().replace("\n", "")
.replace("\r", "")
then:
expected == actual // originally "expected.equals(actual)"
}
}

Notice that even though I didn’t declare main() as “varargs,” I don’t need to put in an empty array in the call from Groovy like I would in a call from Java.

The three warnings surprised me, because I’m clearly using those three java.io classes in the test. Or at least I was in the first draft, it looks like I still need the other two imports.

Since Groovy’s “optionally” typed, it’s not necessary to explicitly declare usualOut as a PrintStream, but I think I still need that identifier for the constructor call to initialize tempOut.

On the other hand, I only needed the OutputStream import because in Java we prefer to use the highest superclass on the left of an equals sign that we can manage. But that still doesn’t explain why the ByteArrayOutputStream and PrintStream imports are not used in this test class in Groovy.

I didn’t realize that Groovy would automatically import everything from the java.io package.

In fact, according to the official Groovy documentation, the Groovy compiler will by default automatically import the following:

import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal

Aside from java.lang, groovy.lang and groovy.util, these choices seem a little arbitrary to me. Nevertheless, when learning a new programming language, it’s a good idea to pay attention to the warnings your integrated development environment reports, not just the errors.

--

--

Alonso Del Arte
Alonso Del Arte

Written by Alonso Del Arte

is a Java and Scala developer from Detroit, Michigan. AWS Cloud Practitioner Foundational certified

No responses yet