spockframework / spockframework/spock

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

Open
#2,410 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
3.6k
Forks
483
PR merge metrics
No merged PRs in 30d

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the supplied AsBooleanGroovy5BugSpec reproduction with Spock 2.4-groovy-5.0 and Groovy 5. Trace the assertion-block AST rewriter to determine where the parenthesized as boolean expression is bypassed; done means the reproduction passes and null or absent map values coerce to false.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy
Domain
testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.