Grailsは:どのようにユニットそれに注入したサービスで、コマンドオブジェクトをテストします

StackOverflow https://stackoverflow.com/questions/1703952

質問

私は、コントローラをテストしようとしています それは、データバインディングとCommandオブジェクトを持っています。

コマンドオブジェクトは、それに注入サービスを持っています。

しかし、私は、コマンドオブジェクトに注入されたサービスメソッドをテストしようとすると それは「注入しない」んとして発見されることはありません。

コマンドオブジェクト内のサービスを模擬する方法はありますか?

試験方法

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
}

UserServiceののの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の" があります。

バリデータは、ユーザーを見つけるために、この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"
          }
      }
 }

userService.getUser()は次のようになります。

class UserService {

    boolean transactional = true

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

    }
}
役に立ちましたか?

解決

サービス注入は、春のautowireバイ名を使用して行われます。 (autowireあなたはそれが統合テストであなたのためにコントローラをautowireするために取得するために使用できる素敵なコードの断片を発見するためにGrailsのソースツリーをGREP。)これだけの機能をSpringアプリケーションコンテキストがあります統合テスト、中にそれは豆を持って周りのこと注入することができます。

ユニットテストでは、あなたは自分のものを取り巻く一切春の土地がありませんので、これを自分で行う必要があります。これは、痛みをすることができますが、あなたはいくつかの利点を提供します:

Expandoを使用して、例えば - -

1)これは、サービスのモックのバージョンを注入するのは簡単ですより密接にあなたのコントローラの協調サービスの動作を指定するために、そしてあなたは、コントローラではなく、唯一のコントローラロジックをテストできるようにすると、一緒にサービス。 (あなたは確かにもユニットテストでは、後者を行うことができますが、あなたはそれを配線方法の選択肢があります。)

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