典型服务如下所示:
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)
}
}
}
使用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类连接了我的Guice。
我很困惑,我应该在哪里创建模拟对象(使用mockito),我应该如何使用Guice连接它们?在ServiceModule或?
中我的设计似乎有误,因为我的BaseService与数据库有连接,我需要以某种方式重构它。
寻找一种摆脱这种糟糕设计的方法,我现在似乎有想法?
答案 0 :(得分:0)
您可以将数据库连接移动到DAO层。您的应用程序应该有三层:controller - >服务 - > DAO。所有服务层需要知道的是DAO提供的功能,即CRUD操作;它不应该知道有关数据库连接的任何信息,因为这是DAO的责任。
我不太确定Slick框架,但对于带Guice的Play框架,它允许禁用" real"在应用程序运行时您期望的绑定(注入依赖项)并启用仅用于此类测试的绑定:
implicit override lazy val app = new GuiceApplicationBuilder()
.configure(appConfig)
.disable(classOf[ReactiveMongoModule], classOf[CommonModule])
.bindings(bind(classOf[ReactiveMongoApi]).toInstance(api))
.bindings(TestDaoModule())
.build()
这是一个完整的集成测试(控制器层),希望它有所帮助:https://github.com/luongbalinh/play-mongo/blob/master/test/controllers/UserControllerTest.scala