grails spock测试失败'java.lang.IllegalArgumentException:ServletContext不能为null'

时间:2014-10-23 09:40:02

标签: java grails spock

我在command class中使用了messageSource.getMessage(...)的方法,因为messageSource不会被注入commandClass。我用

def messageSource = Holders.applicationContext.getBean("messageSource")内的

commandClass

我的问题是在尝试编写unit test此方法时,

@Before
void setup() {
    Holders.applicationContext.getBean("messageSource")
}

void "testFunction"() {
    //inside testFunction I am using messageSource
    given:
        //required things
    when:
        //call the function
    then:
        //assert
}

测试此功能后,我收到错误

java.lang.IllegalArgumentException: ServletContext must not be null at grails.util.Holders.getApplicationContext(Holders.java:80)

有人可以建议如何解决这个问题。

更新

@Validateable
class commandClass {
    //required fields and constraints
    def formatData(List<commandClass> commandObjs) {
        StringBuilder validationErrors
        commandObjs.each {commandObj->
            validationErrors = new StringBuilder()
            if(commandObj.hasErrors()) {
                commandObj.errors.allErrors.each {it ->
                    validationErrors.append(messageSource.getMessage(it, null)).append('\n')
                }
            }
            commandObj.metaClass.validationErrors = validationErrors
        }

    }
} 

先谢谢

3 个答案:

答案 0 :(得分:4)

我找到了答案

void setup() {
    mockApplicationContext()
}

def static mockApplicationContext() {
    GrailsUnitTestMixin.initGrailsApplication()
    Holders.grailsApplication = GrailsUnitTestMixin.grailsApplication
    Holders.metaClass.'static'.getApplicationContext = { ->
        return GrailsUnitTestMixin.applicationContext
    }
    Holders.metaClass.applicationContext.getBean = { bean ->
        return GrailsUnitTestMixin.messageSource
    }
}

我稍后会更新有关答案的更多信息

答案 1 :(得分:2)

============更新的答案========================

现在我正在使用grails 2.4.2。

此处您无需使用Holders.applicationContext.getBean("messageSource")来获取messageSource,它将自动注入。

所以Command对象的例子是:

@Validateable
class Test {
    def messageSource
    String aa

    static constraints = {
    aa blank:false, validator: {val, obj ->
            println obj.messageSource.getMessage("default.paginate.prev",null,LocaleContextHolder.locale)
            ...
        }
    ...

测试的例子:

void "test for valid data"() {
    when:
    def test = new Test(aa:'hello')
    def messageSource = Mock(MessageSource)
    test.messageSource = messageSource
    then:
    test.validate()
}

您也可以使用mockFor。

代替Mock

========= OLD ANSWER ============

您可以在messageSource使用Command object而不是直接使用service messageSource,并service包裹class I18nMessageService { MessageSource messageSource def getMessage(String code, Object[] args=null) { messageSource.getMessage(code,args,LocaleContextHolder.locale) } }

服务的例子:

@Validateable
class Test {
    def i18nMessageService
    String aa

    static constraints = {
        aa blank:false, validator: {val, obj ->
            println obj.i18nMessageService.getMessage("default.paginate.next")
            ...
        }
    }
}

Command对象的示例:

void "test for valid data"() {
    when:
    def test = new Test(aa:'hello')
    def i18nMessageServiceMock = mockFor(I18nMessageService)
    i18nMessageServiceMock.demand.getMessage {'message you wanted'}
    test.i18nMessageService = i18nMessageServiceMock.createMock()
    then:
    test.validate()
}

运行app时,i18nMessageService会自动注入Test命令对象。

对于测试,应该模拟i18nMessageService并手动注入。

测试的例子:

{{1}}

答案 2 :(得分:0)

如果您使用的是Grails 3,则只需添加注释

即可
@TestMixin(GrailsUnitTestMixin)
在课堂定义之前

这将在单元测试中注入一个名为applicationContext的变量。