문제

데이터 바인딩이있는 명령 개체가있는 컨트롤러를 테스트하려고합니다.

명령 객체에 서비스가 주입되어 있습니다.

그러나 명령 개체를 테스트하려고 할 때 주입 된 서비스 방법은 결코 "주입"되지 않으므로 결코 발견되지 않습니다.

명령 개체 내부에서 서비스를 조롱하는 방법이 있습니까?

시험 방법

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
}

사용자 서비스의 getUser () 메소드는 찾을 수 없습니다.

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

암호

호출되는 컨트롤러의 로그인 메소드

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

명령 객체에는 "userservice"가 주입되었습니다.

유효성 검사기는이 사용자 서비스를 호출하여 사용자를 찾습니다

 class LoginCommand {

    def userService

    String login
    String password

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

userervice.getUser ()는 다음과 같습니다.

class UserService {

    boolean transactional = true

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

    }
}
도움이 되었습니까?

해결책

서비스 주입은 Spring Autowire-by-Name을 사용하여 수행됩니다. (성배 소스 트리를 grep autowire 좋은 코드 조각을 찾으려면 통합 테스트에서 컨트롤러를 자동으로 사용하여 사용할 수 있습니다.) 이것은 주변에 주입 할 수있는 콩이있는 스프링 응용 프로그램 컨텍스트가있는 통합 테스트에서만 기능합니다.

단위 테스트에서는 물건을 둘러싼 스프링 랜드가 없기 때문에 직접해야합니다. 이것은 고통 일 수 있지만 몇 가지 이점을 제공합니다.

1) Mock 버전의 서비스를 주입하는 것은 쉽습니다. 예를 들어 Expando - 컨트롤러의 협업 서비스의 동작을보다 면밀히 지정하고 컨트롤러 및 서비스 대신 컨트롤러 로직 만 테스트 할 수 있도록합니다. (단위 테스트에서도 후자를 할 수 있지만이를 연결하는 방법을 선택할 수 있습니다.)

2) 컨트롤러의 종속성에 대해 명시 적으로 강요합니다. 이에 의존하면 테스트에 표시됩니다. 따라서 컨트롤러의 동작에 대한 더 나은 사양이됩니다.

3) 컨트롤러가 의존하는 외부 공동 작업자 만 조롱 할 수 있습니다. 이를 통해 테스트가 깨지기 쉬운 데 도움이됩니다. 상황이 바뀔 때 변화가 필요하지 않습니다.

짧은 답변 : 테스트 방법이 필요합니다 cmd.userService = userService 선.

다른 팁

요한이 말하는 것은 마크에 있습니다. 한 가지 예는 다음과 같습니다.

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

물건을 조롱하는 다른 방법을 조회 할 수 있습니다 http://groovy.codehaus.org/groovy+mocks

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top