使用带有 Groovy 2.6+ 的 Spock 框架来支持 Java 8+ 语法
Using Spock framework with Groovy 2.6+ to support Java 8+ syntax
我有一个使用 JDK 9 语法编译的 Java 库。但是,我正在使用 spock-core:1.0-groovy-2.4
,它不支持 JDK 8+ 语法。因此,在我的 Java 代码中,我可以使用 lambda、默认方法和方法引用。但是,在我的测试中我不能。我必须对 lambda 使用一个笨拙的解决方法,我在其中编写了一个 Groovy 闭包,然后使用 as
关键字将其转换为 Function<...>
。但是,其他语法(例如 Class::method
之类的方法引用)根本无法编译。下面是我的 build.gradle
.
的依赖项部分
我如何升级它,以便我使用支持较新版本 Java 的较新版本 Groovy?
所有文档似乎都已过时,并且仅参考了 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'
)
}
即使在使用 Spock 1.2-groovy-2.4-SNAPSHOT 和 Groovy 3.0.0-alpha-1 时,您也不能直接使用 Java 的 lambda 和方法引用语法,我刚刚在 IntelliJ IDEA 中的示例 Spock/Geb Maven 项目中对其进行了测试。但即使使用 Spock 1.1 和 Groovy 2.4.7,在不强制转换或 as
的情况下替换 lambda 和方法引用也非常简单和优雅,据我在快速测试中所见:
package de.scrum_master.Whosebug
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
}
}
请注意两种不同的调用方式 System.out.println
- 您的选择。 ;-)
控制台日志:
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
你到底错过了什么?
更新: 在我更改了 Maven 项目中的某些内容后,我使用 .map(String.&toUpperCase)
的旧代码不知何故不再工作。我想知道为什么它以前有效。所以我更新了示例代码。
2020 年情况发生了变化。Spock 从版本 2.0-M2.
开始支持 Groovy 3(支持 Java 8+ 增强,包括 lambda 表达式)
对于 Gradle 添加专用于 Groovy 的 Spock 的 JAR 应该足够了 3:
testImplementation('org.spockframework:spock-core:2.0-M2-groovy-3.0')
并启用 JUnit 平台:
test {
useJUnitPlatform()
}
顺便说一句,作为在 Spock 中开发对 Groovy 3 的支持的人,我在 blog post 中收集了与从 Spock 1.3 迁移到 2.0 相关的各个方面(包括注意事项)——这可能值得阅读 :-).
我有一个使用 JDK 9 语法编译的 Java 库。但是,我正在使用 spock-core:1.0-groovy-2.4
,它不支持 JDK 8+ 语法。因此,在我的 Java 代码中,我可以使用 lambda、默认方法和方法引用。但是,在我的测试中我不能。我必须对 lambda 使用一个笨拙的解决方法,我在其中编写了一个 Groovy 闭包,然后使用 as
关键字将其转换为 Function<...>
。但是,其他语法(例如 Class::method
之类的方法引用)根本无法编译。下面是我的 build.gradle
.
我如何升级它,以便我使用支持较新版本 Java 的较新版本 Groovy?
所有文档似乎都已过时,并且仅参考了 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'
)
}
即使在使用 Spock 1.2-groovy-2.4-SNAPSHOT 和 Groovy 3.0.0-alpha-1 时,您也不能直接使用 Java 的 lambda 和方法引用语法,我刚刚在 IntelliJ IDEA 中的示例 Spock/Geb Maven 项目中对其进行了测试。但即使使用 Spock 1.1 和 Groovy 2.4.7,在不强制转换或 as
的情况下替换 lambda 和方法引用也非常简单和优雅,据我在快速测试中所见:
package de.scrum_master.Whosebug
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
}
}
请注意两种不同的调用方式 System.out.println
- 您的选择。 ;-)
控制台日志:
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
你到底错过了什么?
更新: 在我更改了 Maven 项目中的某些内容后,我使用 .map(String.&toUpperCase)
的旧代码不知何故不再工作。我想知道为什么它以前有效。所以我更新了示例代码。
2020 年情况发生了变化。Spock 从版本 2.0-M2.
开始支持 Groovy 3(支持 Java 8+ 增强,包括 lambda 表达式)对于 Gradle 添加专用于 Groovy 的 Spock 的 JAR 应该足够了 3:
testImplementation('org.spockframework:spock-core:2.0-M2-groovy-3.0')
并启用 JUnit 平台:
test {
useJUnitPlatform()
}
顺便说一句,作为在 Spock 中开发对 Groovy 3 的支持的人,我在 blog post 中收集了与从 Spock 1.3 迁移到 2.0 相关的各个方面(包括注意事项)——这可能值得阅读 :-).