2016-09-18 98 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

相關問題