我在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
}
}
}
先谢谢
答案 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的变量。