2017-01-02 30 views
0

我使用的遊戲框架ANORM和我有以下服務類:PlayFramework:如何注入數據庫對象

@javax.inject.Singleton 
class ProductService @Inject() (dbApi: DBApi) { 

    private val DB = dbApi.database("default") 

    def save(product: Product) = { 
    DB.withConnection { implicit connection => 
     .... 
    } 
    } 
} 

兩個問題在這裏:

1)我不希望添加的每個服務類中的行private val DB = dbApi.database("default")。什麼是最好的抽象方式?

2)我也想有數據源配置的,這樣我可以寫集成測試

當通過測試數據源

測試類:

import models.ProductService 
import org.scalatestplus.play.{OneAppPerSuite, PlaySpec} 
import play.api.db.Databases 

class ProductSpec extends PlaySpec with OneAppPerSuite { 

    var productService: ProductService = app.injector.instanceOf(classOf[ProductService]) 

    Databases.withDatabase(
    driver = "com.mysql.jdbc.Driver", 
    url = "jdbc:mysql://localhost/playtest", 
    config = Map(
     "user" -> "test", 
     "password" -> "demo" 
    ) 
) { database => 
    import play.api.db.evolutions._ 
    Evolutions.applyEvolutions(database) 

    "Product" should { 
     "be retrieved by Id" in { 
     val product = productService.get(23) 
     product.get.name must equal("mobile") 
     } 
    } 
    } 

} 

有什麼建議?

回答

2

您可以注入database對象本身而不是DBApi。順便說一句,Guice的最佳做法之一是inject only direct dependencies。所以,你的例子可能是這樣的:

import play.api.db.Database 

@Singleton 
class ProductService @Inject() (database: Database) { 

    def save(product: Product) = { 
    database.withConnection { implicit connection => 
     .... 
    } 
    } 
} 

當然,如果要注入特定數據庫(而不是"default"一個),你可以標註這樣的特性:

import play.api.db.Database 
import play.db.NamedDatabase 

@Singleton 
class ProductService @Inject() (@NamedDatabase("customers") database: Database) { 

    def save(product: Product) = { 
    database.withConnection { implicit connection => 
     .... 
    } 
    } 
} 

而且,在您的測試中,您可以根據需要創建Database並手動將其注入到您的服務中。查看有關如何操作的更多詳細信息at the docs

+0

謝謝,這對於服務類很有用。但是,我無法在Integration測試中使用測試數據庫。我已經將我的測試課程添加到了問題中。在應用進化時,它會嘗試應用到「默認」數據庫(在application.conf中配置),而不是在測試套件中定義的測試數據庫。任何幫助深表感謝。 –