Skip to content

'as boolean' coercion on null/absent property evaluates to null in assertion blocks (Groovy 5) #2410

Description

@sbglasius

Describe the bug

In Spock then: or expect: blocks, using the as boolean operator on a null value or missing map entry—even when explicitly parenthesized—fails to coerce the value to false.

In standard Groovy 5, (null as boolean) == false evaluates to true. However, inside a Spock assertion block in spock-2.4-groovy-5.0, the AST rewriter bypasses the boolean coercion step, leaving the expression as null == false and causing the condition to fail.

To Reproduce

Run the following Specification with spock-core:2.4-groovy-5.0 and groovy:5.0.x:

import spock.lang.Specification

class AsBooleanGroovy5BugSpec extends Specification {

    def "as boolean cast should coerce null map entry to false in assertion block"() {
        given:
        def result = [error: true]

        expect:
        (result.success as boolean) == false
    }
}

Expected behavior

(result.success as boolean) should evaluate to false via Groovy Truth coercion, making false == false pass.

Actual behavior

The test fails with a ConditionNotSatisfiedError. Spock evaluates the left operand as null instead of false:

Condition not satisfied:

(result.success as boolean) == false
 |      |                   |
 |      null                false
 [error:true]

``

Java version

  • Spock Version: 2.4-groovy-5.0
  • Groovy Version: 5.0.x
  • JDK Version: 17+

Buildtool version

------------------------------------------------------------
Gradle 9.6.0
------------------------------------------------------------

Build time:    2026-06-18 23:19:03 UTC
Revision:      3f750f03d77e42327c5f9fcb9992110088330a32

Kotlin:        2.3.21
Groovy:        4.0.32
Ant:           Apache Ant(TM) version 1.10.17 compiled on April 6 2026
Launcher JVM:  25.0.4 (BellSoft 25.0.4+9-LTS)
Daemon JVM:    /home/x/.sdkman/candidates/java/25.0.4-librca (no Daemon JVM specified, using current Java home)
OS:            Linux 6.17.0-1032-oem amd64

What operating system are you using

Linux

Dependencies

org.spockframework:spock-core:2.4-groovy-5.0
+--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT
|    \--- org.apache.grails:grails-bom:8.0.0-SNAPSHOT
|         +--- testCompileClasspath (requested org.apache.grails:grails-bom:8.0.0-M5)
|         +--- edu.berkeley.calnet.grails.plugins:registry-settings:3.0.0-SNAPSHOT
|         |    \--- testCompileClasspath
|         +--- edu.berkeley.calnet.grails.plugins:calnet-ui:3.0.0-SNAPSHOT (requested org.apache.grails:grails-bom:8.0.0-M5)
|         |    \--- testCompileClasspath
|         +--- edu.berkeley.calnet.grails.plugins:ucb-spring-security-cas-ldap:5.0.0-SNAPSHOT
|         |    \--- testCompileClasspath
|         +--- edu.berkeley.calnet.grails.plugins:registry-rest-client:3.0.0-SNAPSHOT (requested org.apache.grails:grails-bom:8.0.0-M5)
|         |    \--- testCompileClasspath
|         \--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
+--- org.apache.grails:grails-bom:8.0.0-SNAPSHOT (*)
+--- org.apache.grails:grails-testing-support-views-gson:8.0.0-SNAPSHOT
|    +--- testCompileClasspath (requested org.apache.grails:grails-testing-support-views-gson)
|    \--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
+--- org.apache.grails.testing:grails-test-core:8.0.0-SNAPSHOT
|    +--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
|    \--- org.apache.grails.testing:grails-testing-support-core:8.0.0-SNAPSHOT
|         +--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
|         \--- org.apache.grails:grails-testing-support-web:8.0.0-SNAPSHOT
|              +--- testCompileClasspath (requested org.apache.grails:grails-testing-support-web)
|              \--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
\--- org.spockframework:spock-bom:2.4-groovy-5.0
     +--- org.apache.grails:grails-base-bom:8.0.0-SNAPSHOT (*)
     +--- org.apache.grails:grails-bom:8.0.0-SNAPSHOT (*)
     \--- org.spockframework:spock-core:2.4-groovy-5.0 (*)

org.spockframework:spock-core -> 2.4-groovy-5.0
\--- testCompileClasspath

Additional context

Work-around

Because as boolean is stripped/ignored by the condition rewriter under Groovy 5, use explicit null checking or defaulting instead:

  • Elvis Operator: (result.success ?: false) == false
  • Map Defaulting: result.get('success', false) == false
  • Groovy Truth Assertion: !result.success

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions