I have a Java library compiled using JDK 9 syntax. But, I am using spock-core:1.0-groovy-2.4
, Which does not support JDK 8+ syntax. So, in my Java code, I can use lambdas, default methods, and method references. But, in my tests I cannot. I have to use a clunky workaround for lambdas where I write a Groovy closure, then cast it to a Function<...>
using the as
keyword. But, other syntax such as method references like Class::method
simply will not compile. Below is the dependencies section of my build.gradle
.
How can I upgrade it such that I am using a newer version of Groovy that supports newer versions of Java?
All of there documentation seems to be out of date, and only references up to Groovy 2.4.
dependencies {
testCompile(
'junit:junit:4.12',
'org.codehaus.groovy:groovy-all:2.4.4',
'org.spockframework:spock-core:1.0-groovy-2.4',
'org.springframework.boot:spring-boot:1.2.1.RELEASE',
'cglib:cglib-nodep:2.2.2',
'com.opencsv:opencsv:4.1'
)
}
Even when working with Spock 1.2-groovy-2.4-SNAPSHOT and Groovy 3.0.0-alpha-1 you cannot directly use Java's lambda and method reference syntax, I just tested it in my sample Spock/Geb Maven project in IntelliJ IDEA. But even with Spock 1.1 and Groovy 2.4.7 it it quite simple and elegant to replace lambdas and method references without casting or as
, as far as I saw in my quick test:
package de.scrum_master.stackoverflow
import groovy.transform.ToString
import groovy.transform.TupleConstructor
import spock.lang.Specification
class LambdaMethodRefTest extends Specification {
def "Replace lambdas and method references in Groovy"() {
given:
def bookStream = [
new Book("Fortran", "Fred", 1957, 57.99),
new Book("Java in 3 Days", "Alice", 2005, 11.99),
new Book("Java in 4 Days", "Bob", 2005, 22.99),
new Book("Filter-Map-Reduce with Lambdas", "Claire", 2014, 33.99)
].stream()
when:
def mapReduceResult = bookStream
.filter { it.year >= 2004 }
.peek(System.out.&println)
.map { it.author }
.map { it.toUpperCase() }
.peek { System.out.println(it) }
.reduce("", { s1, s2 -> (s1.isEmpty()) ? s2 : s1 + ", " + s2 })
then:
mapReduceResult == "ALICE, BOB, CLAIRE"
}
@TupleConstructor
@ToString(includeNames = true, includePackage = false)
static class Book {
String title, author; int year; double price
}
}
Please notice the two different ways of calling System.out.println
- your choice. ;-)
Console log:
LambdaMethodRefTest$Book(title:Java in 3 Days, author:Alice, year:2005, price:11.99)
ALICE
LambdaMethodRefTest$Book(title:Java in 4 Days, author:Bob, year:2005, price:22.99)
BOB
LambdaMethodRefTest$Book(title:Filter-Map-Reduce with Lambdas, author:Claire, year:2014, price:33.99)
CLAIRE
What exactly are you missing?
Update: Somehow my old code using .map(String.&toUpperCase)
is not working anymore after I changed some things in my Maven project. I wonder why it ever worked before. So I have updated the sample code.