2.3. Groovy features useful to Spock tests

Now you have all the essential knowledge needed in order to write your own Spock assertions. The rest of this chapter continues with the theme of reducing unit test code size with the expressiveness provided by Groovy compared to Java. All the following techniques are optional, and you can still use normal Java code in your Spock tests if your organization needs a more gradual change. Each application is different, so it’s hard to predict all the ways that Groovy can help you with unit tests. The following selection is my personal preference.

2.3.1. Using map-based constructors

If there’s one feature of Groovy that I adore, it’s object creation. Most unit tests create new classes either as test data or as services or helper classes used by the class under test. In a large Java application, a lot of statements are wasted creating such objects. The next listing presents a Java example of testing a class that takes as its argument a list of persons.

Listing 2.11. JUnit test with multiple object creation statements

Java needs more than 10 statements to create the two objects that will be used for test input. This boilerplate code is too noisy when compared with the code that tests the Department class.

Easy object creation with Groovy constructors

This is a well-known problem for Java developers. Sometimes special constructors are created for business domain objects to allow for easy testing. I consider this an antipattern. This technique not only shifts verbosity from unit tests to core code, but also has its own shortcomings in the case of multiple constructors. In the preceding example, the Employee class would be polluted with at least two constructors (one that sets the trainee flag and one that ignores it).

Groovy comes to the rescue! Map-based constructors are autogenerated for your Java objects, allowing your Spock tests to initialize any number of fields as well, as shown in the following listing.

Listing 2.12. Spock test with map-based constructors

Without changing a single line of Java code in the Employee class file, I’ve used the map-based constructors, whereby each field is identified by name and the respective value is appended after the semicolon character. Notice that the order of the fields and the set of the fields are completely arbitrary. With this technique,[10] you can create a Java object with all possible combinations of its fields in any order that you like!

10

Groovy supports even-more-concise constructors. They sacrifice clarity, so I refrain from showing them here.

2.3.2. Using maps and lists in Groovy

The syntax shown in the previous section isn’t specific to constructors. This is the Groovy way of initializing a map. You can use it for creating a map in a single statement. The following listing presents an example.

Listing 2.13. Groovy versus Java maps

You can create any kind of map like these, even those with keys and values that are classes on their own. For Groovy, it makes no difference (see the following listing).

Listing 2.14. Groovy maps with nonscalar keys and values

As shown in listing 2.13, when classes are used for the keys of the map, you need to use extra parentheses. If you don’t, the classes are assumed to be strings. Also, this concise Groovy syntax creates by default a LinkedHashMap.

In a similar way to maps, Groovy supports a concise syntax for lists. If you’ve ever wondered why it’s so easy to create an array in Java in a single statement but not a list, you’ll be happy to discover that Groovy has you covered. The following listing shows the comparison between Groovy and Java lists.

Listing 2.15. Groovy versus Java lists

Because the syntax of arrays and lists is similar in Groovy, you might find yourself using arrays less and less as you gain experience with Groovy. Notice that the usual way of declaring arrays in Java is one of the few cases where valid Java is invalid Groovy. If you try to create an array in Groovy by using the Java notation, you’ll get an error, because Groovy uses the same syntax for closures, as you’ll see later in this chapter.

Using the knowledge you’ve gained from the preceding sections, you can completely rewrite the JUnit test from listing 2.11, as the following listing shows.

Listing 2.16. Creating Groovy lists and maps in test code

By following Groovy conventions, I’ve replaced 11 Java statements with 1. The unit test is much more readable because it’s clearly split as far as test data creation and test data usage are concerned.

Accessing lists in Groovy by using array index notation

So far, I’ve demonstrated only how maps and lists are initialized. Let’s see how Groovy improves their usage as well, as shown in the next listing.

Listing 2.17. Using Groovy lists

Notice how writing and reading to a list uses the same syntax, and only the context defines the exact operation. Again, this syntax is optional, and you’re free to use the Java way of doing things even in Spock tests.

Groovy offers the same array-like syntax for maps as well, as shown in the following listing.

Listing 2.18. Using Groovy maps

Lists and maps are one of the many areas where Groovy augments existing Java collections. Groovy comes with its own GDK that sits on top of the existing JDK. You should spend some time exploring the GDK according to your own unit tests and discovering more ways to reduce your existing Java code.

So far, you’ve seen how Groovy enhances classes, fields, and collections. Let’s see how Groovy strings compare to Java strings.

2.3.3. Interpolating text with Groovy strings

I demonstrated Groovy strings (GStrings) at the beginning of this chapter by taking a single Java class and converting it to idiomatic Groovy in a gradual way. At the most basic level, Groovy strings allow for quick text templates of object properties, but they also can handle full expressions, as shown in the following listing.

Listing 2.19. Using Groovy strings

When run, this code prints the following:

>groovy GroovyStrings.groovy
Age is 37
Age is 37
Department location is at block C
Department location is at block C
Person is adult true
Amount in dollars is $300
Person is adult ${employee.age > 18}

Groovy string interpolation is certainly powerful, but for unit tests, their multiline capability is more interesting. Similar to other scripting languages, Groovy allows you to split a big string with newlines, as shown in the next listing.

Listing 2.20. Using Groovy multiline strings

This is a great feature for unit tests that require text input of three to four lines that can be embedded directly on the source file. Multiline strings also support text interpolation if you use double quotes instead of single, but inside unit tests, it’s clearer if they’re pure text (without text interpolation). For more lines of text, I also advise using a separate text file, as demonstrated in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.235.144