2015-07-02 19 views
5

Sto provando a scrivere il test di integrazione per l'applicazione scala (con akka-http). Sto incontrando un problema, per il quale non sono in grado di trovare una soluzione.Sostituisce dinamicamente i valori di campo di un oggetto nidificato

Le mie lezioni di caso sono le seguenti:

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

Ho un metodo come questo

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 
    } 

} 

posso prolungare la mia classe con BaseTrait e basta sovrascrivere il metodo getById(). Il resto degli strati è fornito dalla nostra struttura interna.

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

Così nello strato resto, sarà sempre la risposta come la EmployeeContainer. Il problema che ora sto affrontando è che la data modificata viene automaticamente aggiornata con il timestamp corrente. Quindi, quando ritorno al risultato, il timestamp dell'oggetto passato al metodo save() verrà sovrascritto con l'ora corrente. Quando scrivo il caso di test, ho bisogno di avere un oggetto da confrontare. Ma il timestamp di quell'oggetto e quello che ottengo non sarà mai lo stesso.

C'è comunque, in cui posso sostituire tutte le occorrenze di createDate con un valore noto di timestamp in modo da poterlo confrontare nel mio testcase? Il problema principale è che non posso prevedere la struttura del contenitore (può avere più case classes (nidificate o piatte) con o senza campi createDate).

Sono stato in grado di sostituire il campo utilizzando reflection se è presente nella classe del case principale, ma non è in grado di farlo per le strutture nidificate.

risposta

0

Probabilmente è necessario utilizzare alcuni per Inversion of Control. Il tuo problema principale è che stai chiamando il db direttamente: val emp <- getFromDb(id) e quindi non hai controllo su un test dei valori che vengono ricevuti. Anche chiamare il DB su un test di unità è una cattiva idea, poiché espande l'unità nell'intero livello del database. Vuoi testare una piccola unità autonoma.

Una soluzione semplice è incapsulare le chiamate DB come un'interfaccia e passare un'istanza di tale interfaccia. Per esempio:

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

allora si può semplicemente utilizzare il codice new MyDao(getFromDb) normale e val testDao = new MyDao(id => Employee(id, myFixedName, myFixedDeptID, myFixedTestDate)) dal codice di prova.

Problemi correlati