简体   繁体   English

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

[英]Replace field values of a nested object dynamically

I am trying to write integration test for my scala application(with akka-http ). 我正在尝试为我的scala应用程序编写集成测试(使用akka-http )。 I am running into a problem, for which I am not able to find a solution. 我遇到了一个问题,无法找到解决方案。

My Case classes are as below: 我的案例类如下:

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

I have a method like this 我有这样的方法

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
    }

}

I can extend my class with BaseTrait and just override the getById() method. 我可以使用BaseTrait扩展类,并重写getById()方法。 Rest of the layers are provided by our internal framework. 其余各层由我们的内部框架提供。

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)
   }
}

So in the rest layer, I will be getting the response as the EmployeeContainer . 因此,在其余层中,我将以EmployeeContainer身份获得响应。 The problem now I am facing is that, the modified date is automaticaally updated with the current timestamp. 我现在面临的问题是,修改后的日期会自动使用当前时间戳进行更新。 So, when I get back the result, the timestamp in the object I passed to save() method will be overwritten with the current time. 因此,当我取回结果时,传递给save()方法的对象中的时间戳将被当前时间覆盖。 When I write the test case, I need to have an object to compare to. 在编写测试用例时,需要有一个要比较的对象。 But the timestamp of that object and the one I get abck will never be the same. 但是该对象的时间戳和我收到的对象的时间戳永远不会相同。

Is there anyway, in which I can replace all the occurrance of createDate with a known value of timestamp so that I can compare it in my testcase? 无论如何,我可以用已知的时间戳值替换所有createDate的出现,以便可以在测试用例中进行比较吗? The main problem is that I can not predict the structure of the container (it can have multiple case classes(nested or flat) with or without createDate fields). 主要问题是我无法预测容器的结构(带有或不带有createDate字段的容器可以具有多个案例类(嵌套或平面))。

I was able to replace the field using reflection if it comes in the main case class, but unable to do for nested structures. 如果主案例类中包含reflection则可以使用reflection来替换该字段,但无法对嵌套结构进行操作。

You probably need to use some for of Inversion of Control . 您可能需要将一些用于控制反转 Your main problem is that you are calling the db directly: val emp <- getFromDb(id) and thus have no control on a test of the values that are received. 您的主要问题是直接调用数据库: val emp <- getFromDb(id) ,因此无法控制对接收到的值的测试。 Calling the DB on a unit test is also arguably a bad idea, since it expands the unit to the entire database layer. 在单元测试中调用DB也是一个坏主意,因为它将单元扩展到整个数据库层。 You want to test a small, self-contained unit. 您想测试一个小的独立设备。

A simple solution is to encapsulate your DB calls as an interface and pass an instance of that interface. 一个简单的解决方案是将您的数据库调用封装为一个接口,并传递该接口的实例。 For instance: 例如:

    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)
   }
   }

Then you can simply use new MyDao(getFromDb) for normal code and val testDao = new MyDao(id => Employee(id, myFixedName, myFixedDeptID, myFixedTestDate)) from test code. 然后,您可以简单地将new MyDao(getFromDb)用于常规代码,并从测试代码中使用val testDao = new MyDao(id => Employee(id, myFixedName, myFixedDeptID, myFixedTestDate))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM