PlayでJPAを使用する場合のMock EntityManagerによる単体テスト
-
21-12-2019 - |
質問
DBアクセスのためにJPAを使用するプレイにいくつかの(Scala)コードを持っています。正常に動作します。しかし、Mock EntityManagerを使用する必要があるコードをテストします。これは可能ですか?
マイテストはSPEC2(PlaySpecificationを拡張することによって)で書かれており、JUnitで実行されます。私はMockitoを使ってEntityManagerを偽造しています。しかし、私は他のフレームワークとこれをすることができると期待するでしょう。
これは私のコードがどのように見えるものです:
object MyThing {
def create(...) : MyThing = {
val newThing = ...
JPA.withTransaction(new play.libs.F.Function0[Unit]() {
def apply() = {
JPA.em().persist(newThing)
}
})
return newThing
}
}
.
本規範をテストすることができない場合は、データアクセスへの代替アプローチがありますか?
解決
どうやらここでMock EntityManagerを使用する方法はありません。だから私は私のデザインを修正しなければなりませんでした。
TyptionFeのSargentは、メーリングリストに別のDB永続化サブプロジェクトを作成します。
私はすべてのJPAコードをDAO形質に入れます - すべての実装はそこにあります。シングルトンインスタンスを提供するためのコンパニオンオブジェクトもあります。そのように:
trait MyThingDAO {
def create(...) : MyThing = { ... }
}
object MyThingDAO extends MyThingDAO
.
今度はコントローラを特性に変更して、DAOを残しているDAOを残しました。コンパニオンオブジェクトは、DAOインスタンスをシングルトンオブジェクトに設定します。これにより、ルートファイルに変更を加えることができます(コントローラをインスタンス化する必要はありません)。そのように:
trait MyThingController {
val myThingDao : MyThingDAO
def myAction = Action { implicit request => ... }
}
object MyThingController {
val myThingDao = MyThingDAO
}
.
だからアプリが実行されているときに標準のJPAコードですべてが簡単に機能します。しかし、私がテストを単体テストしたいとき、私はそのようなモックダーを挿入することができます(これはMockitoを使用しています):
...
val mockDao = mock[MyThingDAO]
val controller = new MyThingController() { val myThingDao = mockDao }
...
.
多分これは理想的なアプローチではありませんが、それはこれまでに働いています。私はまだ他の提案を聞くことに興味があるでしょう。