使用带有 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 相关的各个方面(包括注意事项)——这可能值得阅读 :-).