You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 5运行测试时出现GrailsApplication未找到异常求助

解决Grails 5 + Java 11静态类测试中GrailsApplication找不到的问题

问题现象

在Grails 5、Java 11环境下开发插件时,静态类通过grails.util.Holders获取配置项,运行测试时触发以下错误:

java.lang.IllegalArgumentException: GrailsApplication not found
    at org.springframework.util.Assert.notNull(Assert.java:201)
    at grails.util.Holders.getGrailsApplication(Holders.java:129)
    at grails.util.Holders$getGrailsApplication.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)

示例场景

配置文件(YAML)

---
configuration.value: "ABC"

静态类代码

import grails.util.Holders

class SimpleClass {

    static String simpleMethod() {
        return Holders.getGrailsApplication().getConfig().getProperty("configuration.value")
    }
}

测试代码

import spock.lang.Specification

class SomeTest extends Specification {

    void "example"() {
        expect:
        SimpleClass.simpleMethod() == "ABC"
    }
}

报错原因

测试执行阶段,Spring容器尚未完成初始化,Holders静态类中并未持有GrailsApplication实例,调用Holders.getGrailsApplication()时触发非空断言失败。

解决方案

方案一:改用依赖注入(推荐)

放弃使用Holders静态持有,将SimpleClass声明为Spring Bean,通过构造函数注入GrailsApplication:

import grails.core.GrailsApplication
import org.springframework.stereotype.Component

@Component
class SimpleClass {

    private final GrailsApplication grailsApplication

    SimpleClass(GrailsApplication grailsApplication) {
        this.grailsApplication = grailsApplication
    }

    String simpleMethod() {
        return grailsApplication.config.getProperty("configuration.value")
    }
}

对应测试代码修改为:

import spock.lang.Specification
import grails.testing.spring.AutowiredTest

class SomeTest extends Specification implements AutowiredTest {

    SimpleClass simpleClass

    void "example"() {
        expect:
        simpleClass.simpleMethod() == "ABC"
    }
}

方案二:测试中手动初始化Holders(兼容旧代码)

如果必须保留静态方法,可以在测试生命周期中手动设置GrailsApplication到Holders:

import spock.lang.Specification
import grails.testing.runtime.Runtime
import grails.testing.runtime.RuntimeTest
import grails.util.Holders

class SomeTest extends Specification implements RuntimeTest {

    Runtime runtime

    def setup() {
        Holders.setGrailsApplication(runtime.grailsApplication)
    }

    void "example"() {
        expect:
        SimpleClass.simpleMethod() == "ABC"
    }

    def cleanup() {
        Holders.clear()
    }
}

方案三:直接注入配置属性(更简洁)

若仅需获取单个配置值,可直接使用@Value注解注入,无需依赖GrailsApplication:

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class SimpleClass {

    @Value('${configuration.value}')
    String configValue

    String simpleMethod() {
        return configValue
    }
}

测试代码同方案一,通过AutowiredTest注入SimpleClass即可。

内容的提问来源于stack exchange,提问作者Joao G. Hartmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:15:38