动态替换嵌套对象的字段值

时间:2015-07-02 10:04:42

标签: java scala reflection scalatest

我正在尝试为scala应用程序编写集成测试(使用akka-http)。我遇到了一个问题,我无法找到解决方案。

我的案例类如下:

case class Employee(id:Long, name:String, departmentId:Long, createdDate:Timestamp) extends BaseEntity
case class EmployeeContainer(employee:Employee, department:Department)  extends BaseEntity

我有这样的方法

trait BaseTrait[E<:BaseEntity, C <: BaseEntity]{
    def getById(id:Long): Future[List[C]] = {
       //query from db and return result.
    }

    def save(obj:E) = {
      //set the createDate field to the current timestamp
      //insert into database
    }

}

我可以使用BaseTrait扩展我的类,只需覆盖getById()方法。其余层由我们的内部框架提供。

class MyDao extends BaseTrait[Employee, EmployeeContainer] {
  override def getById(id:Long) = {
      for {
      val emp <- getFromDb(id)
      val dept <- DeptDao.getFromDb(emp.departmentId)
      val container = EmployeeContainer(emp,dept)
      } yield(container)
   }
}

所以在休息层,我将得到EmployeeContainer的回复。我现在面临的问题是,修改日期会自动更新当前时间戳。因此,当我返回结果时,传递给save()方法的对象中的时间戳将被当前时间覆盖。当我编写测试用例时,我需要有一个要比较的对象。但是那个对象的时间戳和我得到的对象的时间戳将永远不会相同。

无论如何,我可以用已知的timestamp值替换createDate的所有出现,以便我可以在我的测试用例中进行比较吗?主要问题是我无法预测容器的结构(它可以有多个case类(嵌套或平面),有或没有createDate字段)。

如果它出现在主案例类中,我可以使用reflection替换该字段,但无法对嵌套结构进行替换。

1 个答案:

答案 0 :(得分:0)

你可能需要使用Inversion of Control的一些。您的主要问题是您直接调用db:val emp <- getFromDb(id)因此无法控制对接收到的值的测试。在单元测试中调用DB也可能是一个坏主意,因为它将单元扩展到整个数据库层。你想测试一个小型,独立的单元。

一个简单的解决方案是将您的数据库调用封装为接口并传递该接口的实例。例如:

    class MyDao extends BaseTrait[Employee, EmployeeContainer](val dbCall: Long => Employee) {
  override def getById(id:Long) = {
      for {
      val emp <- dbCall(id)
      val dept <- DeptDao.getFromDb(emp.departmentId)
      val container = EmployeeContainer(emp,dept)
      } yield(container)
   }
   }

然后,您只需将new MyDao(getFromDb)用于普通代码,将val testDao = new MyDao(id => Employee(id, myFixedName, myFixedDeptID, myFixedTestDate))用于测试代码。