2017-01-02 3 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) вместо тестовой базы данных, определенной в наборе тестов. Буду признателен за любую оказанную помощь. –

Смежные вопросы