Domanda

Sto cercando di testare un controller che ha un oggetto Command con l'associazione di dati.

l'oggetto Command ha un servizio iniettato in esso.

Ma quando provo testare il comando oggetto del metodo di servizio iniettato non si trova mai in quanto non è mai "iniettata"

C'è un modo per deridere un servizio all'interno di un oggetto di comando?

Metodo di prova

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
}

Il metodo getUser () della userService non si trova

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

Codice

Il metodo di login del controller di essere chiamato,

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'oggetto Command ha una "userService" iniettato in esso.

Il validatore chiama questa userService per trovare un utente

 class LoginCommand {

    def userService

    String login
    String password

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

L'userService.getUser () assomiglia a questo.

class UserService {

    boolean transactional = true

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

    }
}
È stato utile?

Soluzione

iniezione servizio viene fatto usando Primavera autowire per nome. (Grep l'albero dei sorgenti Grails per autowire di trovare un bel frammento di codice è possibile utilizzare per farlo autowire i controller per voi in test di integrazione). Questo funziona solo in test di integrazione, dove c'è un contesto di applicazione della molla intorno che ha i fagioli che può essere iniettata.

In unit test, dovete farlo da soli perché non c'è Primavera-terreno circostante la tua roba. Questo può essere un dolore, ma ti dà alcuni vantaggi:

1) E 'facile per iniettare versioni finto di servizi - per esempio, utilizzando un Expando - al fine di specificare più da vicino il comportamento dei servizi che collaborano del controller, e per permettere di testare solo la logica di controllo piuttosto che il controllore e servizio insieme. (Si può certamente fare il secondo in una prova di unità pure, ma si ha la scelta di come legare in su.)

2) Ti costringe a essere esplicito circa le dipendenze del vostro controller - se si dipende da esso, i test mostreranno esso. Questo li rende una specifica meglio il comportamento del controllore.

3) Si può prendere in giro solo i pezzi di collaboratori esterni il controller dipende. Questo aiuta i test siano meno fragili -. Meno probabilmente bisogno di cambiare quando le cose cambiano

Risposta breve: il tuo metodo di prova ha bisogno di una linea di cmd.userService = userService

.

Altri suggerimenti

Ciò che Giovanni dice è sul marchio. Un esempio potrebbe essere:

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

Si può cercare altri modi per oggetti mock al http://groovy.codehaus.org/Groovy+Mocks

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top