Scala 如何在使用Guice时设置模拟Dao类?

Scala 如何在使用Guice时设置模拟Dao类?,scala,playframework,guice,scalatest,Scala,Playframework,Guice,Scalatest,典型的服务如下所示: trait BaseService extends LazyLogging { def getDb() = { DatabaseHelper.getDb // database for the scala slick library } } abstract class UserService extends BaseService { def getById(userId: Int): Option[User] } class Us

典型的服务如下所示:

trait BaseService extends LazyLogging {

  def getDb() = {
    DatabaseHelper.getDb       // database for the scala slick library
  }

}

abstract class UserService extends BaseService {
  def getById(userId: Int): Option[User]
}

class UserServiceImpl @Inject(val userDao: UserDao) extends UserService = {

  def getById(userId: Int): Option[User] = {
    getDb().withSession { implicit session =>
         return userDao.getById(userId)
    }
  }
}
implicit override lazy val app = new GuiceApplicationBuilder()
  .configure(appConfig)
  .disable(classOf[ReactiveMongoModule], classOf[CommonModule])
  .bindings(bind(classOf[ReactiveMongoApi]).toInstance(api))
  .bindings(TestDaoModule())
  .build()
我使用Guice连接对象,如:

class ServiceModule extends ScalaModule {
  def configure() {
    bind[UserDao].to[UserDaoImpl]

    bind[UserService].to[UserServiceImpl]
  }
}
现在,当我使用scalatest进行单元测试时,我有点困惑如何将数据库访问解耦,因为我想模拟数据库响应

我的规格看起来像:

class UserServiceSpec extends UnitSpec with MockitoSugar {

val userService = injector.getInstance(classOf[UserService])


describe("UserServiceSpec") {
  it("should do someting") {
    val abc = userService.doSomething();
    abc.name should be("abc")
  }
}


}
我的UnitSpec类连接我的GUI

我很困惑,我应该在哪里创建模拟对象(使用mockito)以及如何使用Guice连接它们?在服务模块中还是

我的设计似乎是错误的,因为我的BaseService与数据库有连接,我需要以某种方式重构它


正在寻找一种方法来摆脱我目前看起来很糟糕的设计,想法?

您可以将db连接移动到DAO层。应用程序应该有三层:控制器->服务->DAO。服务层需要知道的全部是DAO提供的功能,即CRUD操作;它不应该知道任何关于db连接的事情,因为这是DAO的责任

我对Slick framework不是很确定,但对于使用Guice的Play framework,它允许禁用应用程序运行时预期的“真实”绑定(注入的依赖项),并启用仅用于以下测试的绑定:

trait BaseService extends LazyLogging {

  def getDb() = {
    DatabaseHelper.getDb       // database for the scala slick library
  }

}

abstract class UserService extends BaseService {
  def getById(userId: Int): Option[User]
}

class UserServiceImpl @Inject(val userDao: UserDao) extends UserService = {

  def getById(userId: Int): Option[User] = {
    getDb().withSession { implicit session =>
         return userDao.getById(userId)
    }
  }
}
implicit override lazy val app = new GuiceApplicationBuilder()
  .configure(appConfig)
  .disable(classOf[ReactiveMongoModule], classOf[CommonModule])
  .bindings(bind(classOf[ReactiveMongoApi]).toInstance(api))
  .bindings(TestDaoModule())
  .build()

这是一个完整的集成测试(控制器层),希望对您有所帮助:

我不知道guice+scala,但对于Java,您可以使用Modules.override()添加一个将UserDao绑定到模拟(UserDao)实例的模块。您能在单元测试中完全避免使用guice吗?“我会这么做的。”塔维安巴恩斯说,“可能吧,我没想过。”。还有一个问题是,我的数据库池位于基本服务中,我需要以某种方式解决。