4

私は、ある種のモック SecureSocial アクション ジェネレーター、または SecureSocial 自体を発明して、コントローラー メソッドを単体テストできるようにしようとしています。Securesocialアノテーションで保護された単体テスト方法、依存性注入を使用してSecureSocialでPlay2アプリケーションをテストするなど、いくつかのアプローチを見つけましたが、実際には、その質問の作者は単体テストを行うのではなく、統合テストを行います.

私の単体テストは次のようになります。

  trait MockDaoProvider extends IDaoProvider {
    def entityDao = entityDaoMock
  }

  val controller = new MyController with MockDaoProvider

  "MyController.list" should {
    "return an OK" in {
      entityDaoMock.list().returns(List())

      val result = controller.list()(FakeRequest())

      status(result) must equalTo(OK)
    }
  }

ご覧のとおり、依存関係をモックして、コントローラー メソッドが実際に行う動作を分離してテストしました。

MyController.list メソッドに securesocial の SecuredAction を使用するまでは、すべて問題ありませんでした。今度は例外が発生し、テストは失敗します。securesocial から SecuredAction および UserAwareAction オブジェクトをモック、スタブ、またはオーバーライドする方法がわかりません。それでも、テストを route(...) テストに変換したくありません。これらは、コントローラーの動作のみをテストすることを目的としています。

誰かが同じ問題に遭遇しましたか? どのように解決できるかのヒントがあるかもしれませんか?

PS: Play フレームワーク 2.2.1、securesocial - 2.1.2

4

2 に答える 2

3

コードの作成者はテスト容易性をあまり重視していないようで、ユーザーは独自の斬新なソリューションを考え出す必要がありました。ユーザー jeantil によるこの 1 つが役立つ場合があります。

class FakeAuthenticatorStore(app:Application) extends AuthenticatorStore(app) {
  var authenticator:Option[Authenticator] = None
  def save(authenticator: Authenticator): Either[Error, Unit] = {
    this.authenticator=Some(authenticator)
    Right()
  }
  def find(id: String): Either[Error, Option[Authenticator]] = {
    Some(authenticator.filter(_.id == id)).toRight(new Error("no such authenticator"))
  }
  def delete(id: String): Either[Error, Unit] = {
    this.authenticator=None
    Right()
  }
}

abstract class WithLoggedUser(val user:User,override val app: FakeApplication = FakeApplication()) extends WithApplication(app) with Mockito{
  lazy val mockUserService=mock[UserService]
  val identity=IdentityUser(Defaults.googleId, user)

  import helpers._
  import TestUsers._
  def cookie=Authenticator.create(identity) match {
    case Right(authenticator) => authenticator.toCookie
  }

  override def around[T: AsResult](t: =>T): execute.Result = super.around {
    mockUserService.find(Defaults.googleId) returns Some(identity)
    UserService.setService(mockUserService)
    t
  }
}

  val excludedPlugins=List(
    ,"service.login.MongoUserService"
    ,"securesocial.core.DefaultAuthenticatorStore"
  )
  val includedPlugins = List(
    "helpers.FakeAuthenticatorStore"
  )

  def minimalApp = FakeApplication(withGlobal =minimalGlobal, withoutPlugins=excludedPlugins,additionalPlugins = includedPlugins)

これにより、このようなテストが可能になります

"create a new user password " in new WithLoggedUser(socialUser,minimalApp) {
  val controller = new TestController
  val req: Request[AnyContent] = FakeRequest().
    withHeaders((HeaderNames.CONTENT_TYPE, "application/x-www-form-urlencoded")).
    withCookies(cookie) // Fake cookie from the WithloggedUser trait

  val requestBody = Enumerator("password=foobarkix".getBytes) andThen Enumerator.eof
  val result = requestBody |>>> controller.create.apply(req)

  val actual: Int= status(result)
  actual must be equalTo 201
}
于 2014-01-26T17:17:12.693 に答える