首页 文章

在Play中使用JPA时使用模拟EntityManager进行单元测试

提问于
浏览
1

我在Play中有一些(Scala)代码,它使用JPA进行数据库访问 . 工作良好 . 但我想对我的代码进行单元测试,这需要使用模拟EntityManager . 这可能吗?

我的测试是用specs2编写的(通过扩展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
    }
}

如果无法对此代码进行单元测试,是否建议使用其他替代数据访问方法?

1 回答

  • 0

    显然,这里没有办法使用模拟EntityManager,至少没有我能找到的 . 所以我不得不修改我的设计 .

    Typesafe的Sargent建议在邮件列表上创建一个单独的数据库持久性子项目:https://groups.google.com/d/msg/play-framework/1u-_JbTIuQg/L5_9o4YCfoMJ . 我还没有走得那么远,但我确实通过定义一个单独的DAO接口找到了一个对我有用的解决方案 .

    我将所有JPA代码放入DAO特征 - 所有实现都在那里 . 还有一个伴随对象来提供单例实例 . 像这样:

    trait MyThingDAO {
        def create(...) : MyThing = { ... }
    }
    object MyThingDAO extends MyThingDAO
    

    现在我将控制器更改为traits,并引用了未设置的DAO . 伴随对象将DAO实例设置为单例对象 . 这样可以避免对routes文件进行任何更改(无需实例化控制器) . 像这样:

    trait MyThingController {
        val myThingDao : MyThingDAO
        def myAction = Action { implicit request => ... }
    }
    object MyThingController {
        val myThingDao = MyThingDAO
    }
    

    因此,当应用程序运行时,所有内容都可以使用标准JPA代码轻松完成 . 但是当我想进行单元测试时,我可以像这样插入一个模拟DAO(这是使用Mockito):

    ...
    val mockDao = mock[MyThingDAO]
    val controller = new MyThingController() { val myThingDao = mockDao }
    ...
    

    也许这不是理想的方法,但它到目前为止一直在努力 . 我仍然有兴趣听到任何其他建议 .

相关问题