2016-09-18 97 views
0

播放文档说“内存数据库中的H2对于开发非常方便,因为您的演变在重新开始播放时从头开始运行。”这就是我想要的。这里是我迄今所做的(播放2.5.6):使用H2内存数据库设置Scala Play测试

  1. 我创建使用H2与演化测试配置文件,内容如下:

    play.evolutions { 
        db.default.enabled = true 
        autoApply = true 
    } 
    
    db { 
        default { 
        driver = org.h2.Driver 
        url = "jdbc:h2:mem:test;MODE=MYSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1" 
        username = sa 
        password = "" 
        pool = "bonecp" // otherwise you can't log your sql... 
        bonecp.logStatements=true 
        } 
    } 
    
  2. 我添加了一个简单演化文件“/conf/evolutions/default/1.sql”:

    # --- !Ups 
    
    CREATE TABLE PROJECTS (
        id int(11) NOT NULL 
    ) ; 
    
    # --- !Downs 
    
    DROP TABLE IF EXISTS PROJECTS; 
    
  3. 我的控制器需要一个数据库。这是测试数据库应该被注入而不是MySQL的地方。它有一个测试的行动,读取表:

    class DataManagementController @Inject()(db: Database) extends Controller { 
    
         def test() = Action { 
         db.withConnection { conn => 
          val st = conn.createStatement() 
          val res = st.executeQuery("SELECT * FROM PROJECTS") 
          while (res.next()) { println(res.getInt("id")) } 
         } 
         Ok("") 
         } 
    } 
    
  4. ,我写我的行动的第一个测试如下:

    class ControllerSpec extends PlaySpec with OneAppPerSuite { 
    
        val TestDb = Databases.inMemory("default") 
        val dataCtrl = new DataManagementController(TestDb) 
    
        "DataManagementController" should { 
        "test" in { 
         dataCtrl.test().apply(FakeRequest()) 
        } 
        } 
    } 
    
  5. 当我运行测试,我看到变阵得到应用到H2分贝,但在查询运行时,每样东西尽管DB_CLOSE_DELAY=-1选项删除(?):

    ~ test-only ControllerSpec 
    
    [info] ControllerSpec: 
    [debug] c.j.b.BoneCPDataSource - JDBC URL = jdbc:h2:mem:test;MODE=MYSQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1, Username = sa, partitions = 1, max (per partition) = 30, min (per partition) = 5, idle max age = 10 min, idle test period = 1 min, strategy = DEFAULT 
    [debug] c.j.b.StatementHandle - select id, hash, apply_script, revert_script, state, last_problem from play_evolutions where state like 'applying_%' 
    [error] o.j.StatementLogger - java.sql.Statement.executeQuery: select id, hash, apply_script, revert_script, state, last_problem from play_evolutions where state like 'applying_%'; 
    throws exception: org.h2.jdbc.JdbcSQLException: Table "play_evolutions" not found; SQL statement: 
    select id, hash, apply_script, revert_script, state, last_problem from play_evolutions where state like 'applying_%' [42102-192] 
    [...] 
    [debug] c.j.b.StatementHandle - 
        create table play_evolutions (
    [...] 
    [debug] c.j.b.StatementHandle - CREATE TABLE PROJECTS (
        id int(11) NOT NULL AUTO_INCREMENT, 
        person_id int(11) NOT NULL, 
        name varchar(255) NOT NULL, 
        PRIMARY KEY (id), 
    ) 
    [debug] c.j.b.StatementHandle - update play_evolutions set state = 'applied' where id = 1 
    [debug] c.j.b.StatementHandle - select id, hash, apply_script, revert_script, state, last_problem from play_evolutions where state like 'applying_%' 
    
    [info] DataManagementController 
    [info] application - Creating Pool for datasource 'default' 
    [info] - should test *** FAILED *** 
    [info] org.h2.jdbc.JdbcSQLException: Table "PROJECTS" not found; 
    [...] 
    

    如果我和探索数据库(url:“jdbc:h2:mem:test”+ args),它是空的。但是,如果我现在修改“1.SQL”,我得到

    Database 'default' is in an inconsistent state![An evolution has not been applied properly. Please check the problem and resolve it manually before marking it as resolved.] 
    

    ,但它并没有说如何解决这个问题(因为我在浏览器中看到一个空数据库)。

我将不胜感激设置测试数据库的任何帮助。我在这里看到很多帖子提出类似的问题,无论是没有答案,也没有接受,有几种不同的方法,而且我几乎一直在努力尝试几天。注:它将在StackOverflow文档(和Play文档btw)中做出有用的部分。

+0

也可以看看http://tour.acolyte.eu.org/ – cchantep

回答

1

我还没有对照Play 2.5进行检查,但我预计这与最新的2.4版本非常相似。

在这里了解组件的生命周期很重要。您的测试设置的方式实际上涉及两个H2数据库。

  1. test由PlaySpec根据您提供的测试配置进行管理。这通常需要使用WithApplication。这里DB_CLOSE_DELAY设置正确。

  2. 您正在对自己创建的H2数据库default进行测试。DB_CLOSE_DELAY未设置此实例,但你可以提供地图urlOptions的:

    ​​

有几个选项(但不尝试完成):

  1. 使用一个普通的Specs2规范而不是PlaySpec。这样您就可以避免在后台运行假冒的Play应用。但是你不会从Play的演变中受益。

    应用使用H2和URL选项INIT=RUNSCRIPT FROM 'classpath:evolutions/default/1.sql'

  2. 点数据库中的规范对test而非default,以确保您连接到同一个数据库,并使用WithApplication让玩家管理迁移/插入测试夹具它。

  3. 相反实例您在测试控制器,你也可以让Play的路由器做到这一点,调用操作。检出文件here

+0

谢谢,它有很多帮助。我应该放弃拥有2个设置文件吗?我不知道测试数据库是否应该在配置文件,假应用程序中,Guice覆盖中定义,或者像我一样直接实例化。我真的不需要选择,而是一种最好的方式来为我的未来应用程序创建一个测试数据库,并使用依赖注入。 – JulienD

+1

很难给出明确的建议,有很多优点和缺点。 使用'WithApplication'确实很简单,它为您的应用程序带来了便利。但是,您仅限于一个数据库/因此一次只能有一个Play应用程序。所以你不能并行地运行你的测试,因为你不能将它们隔离开来,它们可能会发生冲突。个人而言,对我来说,这是一个无赖,但对于一个小应用程序,它可能不是一个大问题。如果你正在寻找一个快速的方法,我会建议保持测试配置,并尝试一下。检查文档的链接,这是相当有用的... – Moritz

+0

谢谢。我多次阅读这些链接。选项3意味着以某种方式创建一个假的隐式'app'(我不知道如何将我的db注入到该模板中,尽管我试着用Guice将复杂的东西花费了几个小时,在SO上发布了一个问题并没有回答),他们自己说在为每个测试/套件创建整个应用程序实例的文档中并不好。 – JulienD

相关问题