Question

Je suis en train de tester un contrôleur qui a un objet de commande avec liaison de données.

L'objet de commande a un service injecté en elle.

Mais quand j'essaie de tester la commande objet de la méthode de service injecté est jamais trouvé qu'il est jamais « injecté »

Y at-il un moyen de se moquer d'un service à l'intérieur d'un objet de commande?

Méthode d'essai

void testLoginPasswordInvalid() {
    mockRequest.method = 'POST'
    mockDomain(User, [new User(login:"freddy", password:"realpassword")])
    mockLogging(UserService) // userService mocked
    MockUtils.prepareForConstraintsTests(LoginCommand)

    def userService = new UserService()
    def user = userService.getUser("freddy")//Gets called and returns the mockDomain
    assert userService.getUser("freddy")//Passes

    def cmd = new LoginCommand(login:"freddy", password:"letmein")
    cmd.validate() // Fails (userService is nevr injected)
    controller.login(cmd)
    assertTrue cmd.hasErrors()
    assertEquals "user.password.invalid", cmd.errors.password
    assertEquals "/store/index", renderArgs.view
}

La méthode getUser () de la UserService ne se trouve pas

Cannot invoke method getUser() on null object
java.lang.NullPointerException: Cannot invoke method getUser() on null object

code

La méthode de connexion de l'unité de commande étant appelée,

def login = { LoginCommand cmd ->
  if(request.method == 'POST') {
     if(!cmd.hasErrors()){
       session.user = cmd.getUser()
       redirect(controller:'store')
     }
     else{
       render(view:'/store/index', model:[loginCmd:cmd])
     }
  }else{

    render(view:'/store/index')
  }
}

L'objet de commande a une "UserService" injecté en elle.

Le validateur appelle cette UserService pour trouver un utilisateur

 class LoginCommand {

    def userService

    String login
    String password

    static constraints = {
      login blank:false, validator:{ val, cmd ->
          if(!cmd.userService.getUser()){
             return "user.not.found"
          }
      }
 }

Le userService.getUser () ressemble à ceci.

class UserService {

    boolean transactional = true

    User getUser(String login) {
        return User.findByLogin(login)

    }
}
Était-ce utile?

La solution

injection de service est effectuée à l'aide par nom autowire-Spring. (GREP l'arbre source Grails pour autowire trouver un beau fragment de code que vous pouvez utiliser pour obtenir à autowire vos contrôleurs pour vous dans les tests d'intégration.) Cela ne fonctionne que dans les tests d'intégration, où il y a un contexte d'application Spring autour qui a les haricots peut être injecté.

Dans les tests unitaires, vous devez faire vous-même car il n'y a pas de printemps-terre entourant vos affaires. Cela peut être une douleur, mais vous donne quelques avantages:

1) Il est facile d'injecter des versions fausses de services - par exemple, en utilisant un Expando - afin de préciser davantage le comportement des services de collaboration de votre contrôleur, et pour vous permettre de tester uniquement la logique de commande plutôt que le contrôleur et service ensemble. (Vous pouvez certainement faire ce dernier dans un test unitaire aussi bien, mais vous avez le choix de la façon de le câbler.)

2) Il vous oblige à être explicite sur les dépendances de votre contrôleur - si vous dépendez, vos tests montrer. Cela leur fait une meilleure spécification pour le comportement de votre contrôleur.

3) Vous pouvez seulement se moquer des morceaux de collaborateurs externes de votre contrôleur dépend. Cela aide vos tests soient moins fragiles -. Moins susceptibles d'avoir besoin de changer quand les choses changent

Réponse courte: votre méthode de test a besoin d'une ligne de cmd.userService = userService

.

Autres conseils

Ce que dit John est sur la marque. Un exemple pourrait être:

def mockUsers = [new User(login:"freddy", password:"realpassword")]
mockDomain(User, mockUsers)

def userService = [getUser:{String login -> mockUsers[0]}] as UserService

def cmd = new LoginCommand (/*arguments*/)
cmd.userService = userService

Vous pouvez rechercher d'autres façons d'objets fantaisie http://groovy.codehaus.org/Groovy+Mocks

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top