Grails spock testing with the error "java.lang.IllegalArgumentException: ServletContext must not be null"

I have a method in the command class that uses messageSource.getMessage(...) since messageSource will not be injected into commandClass . I use

def messageSource = Holders.applicationContext.getBean("messageSource") inside commandClass .

My problem is trying to write unit test this method,

 @Before void setup() { Holders.applicationContext.getBean("messageSource") } void "testFunction"() { //inside testFunction I am using messageSource given: //required things when: //call the function then: //assert } 

after testing this function I get an error

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

Can someone suggest how to solve this problem.

Update

 @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 } } } 

Thanks at Advance

+6
source share
3 answers

I found the answer

 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 } } 

I will tell you about the answer again

+5
source

============= UPDATED ANSWER =================================

I am using grails 2.4.2 now.

Here you do not need to use Holders.applicationContext.getBean("messageSource") to receive a messageSource, it will be automatically entered.

So, an example Command object:

 @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) ... } ... 

Test example:

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

Instead of Mock, you can also use mockFor.

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

Instead of directly using messageSource in a Command object you can use service there and wrap messageSource with service .

Service example:

 class I18nMessageService { MessageSource messageSource def getMessage(String code, Object[] args=null) { messageSource.getMessage(code,args,LocaleContextHolder.locale) } } 

Command object example:

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

The i18nMessageService service is automatically injected into the Test command object during application startup.

For the i18nMessageService test, you must mock and enter manually.

Test example:

 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() } 
+2
source

If you are using Grails 3, just add an annotation

 @TestMixin(GrailsUnitTestMixin) 

before defining your class.

This will bring a variable called applicationContext into your unit test.

0
source

Source: https://habr.com/ru/post/977119/


All Articles