2017-03-19 4 views
0

J'ai un objet de commande avec des contraintes à l'aide de grains de printemps dans validateur personnalisé:Grails. objets de commande Test avec des haricots de ressort à l'intérieur

class UserPasswordCommand { 
    String currentPassword 
    //other fields.... 
    static constraints = { 
     currentPassword validator: { currPass, upc -> 
      Holders.applicationContext.passwordEncoder.isPasswordValid(
        Holders.applicationContext.springSecurityService.currentUser.password, currPass, null) 
     } 
    } 
} 

Mais lors de l'appel nouvelle UserPasswordCommand (...) dans le test de l'unité que je reçois le texte suivant:

java.lang.NullPointerException: Impossible d'obtenir la propriété 'currentUser' sur objet null

Il semble donc que springSecurityService = null (comme prévu). J'ai essayé différentes actions pour se moquer ou "métaClass" mais ça n'a pas réussi.

Veuillez indiquer s'il existe une meilleure façon d'utiliser les beans d'applicationContext dans les objets de commande ou certaines approches de bockage de beans dans Holders.applicationContext.

Merci d'avance!

MISE À JOUR

Placé ce qui suit à setup() section:

def setup() { 
    def appContext = Mock(ApplicationContext) 
    def springSecurityService = Mock(SpringSecurityService) 
    appContext.springSecurityService >> springSecurityService 
    Holders.metaClass.static.applicationContext = { appContext } 
} 

Mais aucun effet. springSecurityService est null dans applicationContext récupéré à partir de Supports. Qu'est-ce que je fais mal?

+0

Juste FYI en utilisant Holders dans un objet de commande est une très mauvaise idée. Cela fonctionnera mal. La meilleure façon de le faire est de faire les arguments du constructeur des beans et de construire la classe vous-même. –

+0

@ JamesKleeh, merci pour info. J'ai changé la récupération de Holders à un DI normal et ai rendu les champs statiques. Cette solution est-elle assez bonne? –

Répondre

0

je résolu le problème en se débarrassant de Holders dans l'objet de commande d'origine:

class UserPasswordCommand { 
    static passwordEncoder 
    static springSecurityService 
    String currentPassword 
    //... 
    static constraints = { 
     currentPassword validator: { currPass, upc -> 
    passwordEncoder.isPasswordValid(springSecurityService.currentUser.password, currPass, null) 
     } 
    //... 
    } 
} 

Ajouté les Mocks/talons pour tester essai :

def springSecurityService = Mock(SpringSecurityService) 
def passwordEncoder = Mock(PasswordEncoder) 

def setup() { 
    passwordEncoder.isPasswordValid(_, _, _) >> Boolean.TRUE 
    springSecurityService.currentUser >> Mock(User) 
} 

et:

given: 
Map props = [ 
    currentPassword: CURRENT_PASSWORD, 
    passwordEncoder: passwordEncoder, 
    springSecurityService: springSecurityService, 
] 

expect: 
new UserPasswordCommand(props).validate() 
0

Vous pouvez remplacer Holder.applicationContext comme ceci:

def setup() { 
    ApplicationContext appContext = Mock() 
    PasswordEncoder passwordEncoder = Mock() 
    passwordEncoder.isPasswordValid(_, _, _) >> true 

    appContext.passwordEncoder >> passwordEncoder //you can do the same for springSecurityService 

    //override Holder.getAplicationContext() method to return mocked context 
    Holders.metaClass.static.applicationContext = { appContext } 
} 
+0

Voulez-vous dire 'Holders' au lieu de' Holder'? Et probablement 'metaClass' au lieu de' metaclass'? –

+0

Oui, désolé je n'avais pas accès au carnet, je viens de corriger ma réponse – rgrebski

+0

Aucun effet. J'ai mis à jour la question avec la nouvelle section 'setup()'. –