Frage

Ich versuche, einen Controller zu testen das hat ein Command-Objekt mit Datenbindung.

Das Command-Objekt hat einen Dienst hinein injiziert.

Aber wenn ich testen, versuchen, den Befehl des injizierten Service-Methode Objekt ist nie wie es nie „injiziert“

gefunden

Gibt es eine Möglichkeit, einen Dienst in einem Befehl Objekt zu verspotten?

Testmethode

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
}

Der getUser () -Methode des Userservice nicht gefunden

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

Code

Das Anmeldeverfahren des Controller aufgerufen wird,

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

Das Command-Objekt hat eine "Userservice" injiziert hinein.

Der Validator nennt diesen Userservice um einen Benutzer zu finden

 class LoginCommand {

    def userService

    String login
    String password

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

Die userService.getUser () sieht wie folgt aus.

class UserService {

    boolean transactional = true

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

    }
}
War es hilfreich?

Lösung

Service Einspritzung mit Spring autowire-by-Namen getan. (Grep die Grails-Source-Tree für autowire einen schönen Codefragment finden Sie es verwenden, um Ihre Controller für Sie in Integrationstests autowire.) Das funktioniert aber nur in Integrationstests, wo es ein Spring-Anwendungskontext um, dass die Bohnen hat, dass injiziert werden kann.

In Unit-Tests, müssen Sie dies selbst tun, da es keinen Frühling Land Ihre Sachen umgibt. Dies kann ein Schmerz sein, aber gibt Ihnen einige Vorteile:

1) Es ist einfach Mock Versionen von Dienstleistungen zu injizieren - zum Beispiel eines Expando mit - um genauer, um das Verhalten des Controllers kollaborierenden Dienste angeben, und ermöglicht es Ihnen, nur die Controller-Logik, anstatt die Steuerung zu testen und Service zusammen. (Sie können natürlich auch die letztere in einem Unit-Test tun, aber Sie haben die Wahl, wie es verkabeln.)

2) Es zwingt Sie über die Abhängigkeiten von dem Controller explizit zu sein - wenn Sie davon abhängen, Ihre Tests es zeigen. Das macht sie eine bessere Beschreibung für das Verhalten des Controllers.

3) Sie können nur die Stücke von externen Mitarbeitern verspotten Ihre Steuerung abhängt. Dies hilft, Ihre Tests weniger zerbrechlich sein -. Weniger wahrscheinlich ändern zu müssen, wenn die Dinge ändern

Kurze Antwort: Ihre Testmethode benötigt eine cmd.userService = userService Zeile

.

Andere Tipps

Was John sagt, ist auf die Marke. Ein Beispiel könnte sein:

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

Sie können Nachschlag andere Wege, um Mock-Objekte unter http://groovy.codehaus.org/Groovy+Mocks

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top