2014-10-23 12 views
6

ich eine Methode in command class aufweist, die messageSource.getMessage(...) verwenden, da Message nicht in die commandClass injiziert bekommen. Ich verwendegrails Spöck Testen mit Herzinsuffizienz ‚java.lang.IllegalArgumentException: ServletContext nicht null sein muss‘

def messageSource = Holders.applicationContext.getBean("messageSource") innerhalb der commandClass.

Mein Problem ist, wenn unit test diese Methode zu schreiben versucht,

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

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

nach Überprüfung dieser Funktion ich den Fehler bekommen

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

jemand, wie dieses ein vorschlagen kann zu lösen.

aktualisieren

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

    } 
} 

Vielen Dank im Voraus

+0

Bitte geben Sie die Befehlsklasse in der Frage? – Ramsharan

Antwort

5

ich die Antwort

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

gefunden werde ich mehr über die Antwort aktualisieren später

2

============ AKTUALISIERT ANTWORT ============== ==========

Momentan verwende ich grails 2.4.2.

Hier müssen Sie nicht Holders.applicationContext.getBean("messageSource") verwenden, um messageSource zu erhalten, es wird automatisch injiziert.

So das Beispiel des Objekts Befehl:

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

Das Beispiel des Tests:

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

Statt Mock, können Sie auch mockFor verwenden.

========= ALTE ANTWORT ============

Statt direkt messageSource in Command object verwenden, können Sie service dort verwenden und wickeln Sie das messageSource durch die service.

Das Beispiel des Dienstes:

class I18nMessageService { 
    MessageSource messageSource 

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

Das Beispiel des Objekts Befehl:

@Validateable 
class Test { 
    def i18nMessageService 
    String aa 

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

Die i18nMessageService automatisch an das Testkommando Objekt injiziert wird, während App ausgeführt wird.

Für den Test sollte i18nMessageService mocked und manuell injiziert werden.

Das Beispiel des Tests:

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

Danke für Ihre Antwort, können wir direkt 'MessageSource' verwenden, innerhalb der Befehlsklasse nur richtig? –

+0

Welche Version von Grails verwendest du? – Ramsharan

+0

'Grails 2.3.8' Version –

0

Wenn Sie Grails verwenden 3, die Sie gerade um die Anmerkung hinzuzufügen

@TestMixin(GrailsUnitTestMixin) 

vor Ihrer Klassendefinition.

Dadurch wird in Ihrem Komponententest eine Variable namens applicationContext eingefügt.