dependency injection - How would I inject a mocked singleton object in Scala? -


we're using scala 2.10.2, , we're using slick 1.0.1 our daos. we're trying mock daos scalamock, , i'm trying figure out way inject mocked daos. i've used java several years, i've started using scala 2 weeks ago.

right our code looks (ignore syntax errors, i've condensed code without making sure still satisfies type system)

abstract class richtable[t](name: string)          extends slick.driver.mysqldriver.simple.table[t](name) {     type itemtype = t     def id = column[int]("id", o.primarykey, o.autoinc)     ... }  object users extends richtable[user]("users") {     def crypted_password = column[string]("crypted_password")     ... }  case class user(id: option[int] = none, crypted_password: string) {     def updatepassword(...) = {         users.where(_.id === id).map{e => e.crypted_password}.update("asdf")     } } 

all of daos singleton objects inheriting richtable[t]

we'd able mock users , other singleton dao objects - right of our unit tests hitting database. however, problem we're running how inject mock singleton objects. solution we've come far is:

object daorepo {     var usersdao : users.type = users     var anotherdao : another.type =     ... }  object users extends richtable[user]("users") {     def apply() : users.type = daorepos.usersdao }  def updatepassword(...) = {     users().where(_.id === id).map{e => e.crypted_password}.update("asdf") }  def test = {     val mockusers = mock[users]     daorepo.usersdao = mockusers     // run test using mock repo } 

we're changing of our references users users(), doesn't add excessive amount of clutter. however, use of vars in daorepo smells bad, , i'm wondering if has suggestion improve this.

i've read real-world scala: dependency injection (di) , component based dependency injection in scala - think understand how use traits compose daorepo, like

trait usersrepo {     val usersdao : users.type = users }  trait daorepo extends usersrepo anotherrepo { }  trait userstestrepo {     val usersdao : users.type = mock[users] } 

but still don't understand how i'd inject new trait. like

class daorepoimpl extends daorepo { }  object daowrapper {     var repo : daorepo = new daorepoimpl }  def test = {     daowrapper.repo = new daorepoimpl userstestrepo } 

which replaces 2 dozen vars in object daorepo single var in object daowrapper, seems there ought clean way without vars.

i don't understand classes , traits.

trait usersrepo {     val usersdao : users.type = users }  trait anotherrepo {     val anotherdao : another.type = }  trait daorepo extends usersrepo anotherrepo 

and can instantiate real realdaorepo

object realdaorepo extends daorepo { } 

or mocked one

object mockeddaorepo extends daorepo {   override val usersdao : users.type = mock[users]   override val anotherdao : another.type = mock[another] } 

then inject daorepo in application can use cake pattern , self type references that.


i'll publish article on infoq fr helps spring people understand cake pattern. here's code sample article:

trait usertweetservicecomponent {   val usertweetservice: usertweetservice }  trait usertweetservice {   def createuser(user: user): user   def createtweet(tweet: tweet): tweet   def getuser(id: string): user   def gettweet(id: string): tweet   def getuserandtweets(id: string): (user,list[tweet]) }  trait defaultusertweetservicecomponent extends usertweetservicecomponent {    // declare dependencies of service here   self: userrepositorycomponent          tweetrepositorycomponent =>    override val usertweetservice: usertweetservice = new defaultusertweetservice    class defaultusertweetservice extends usertweetservice {     override def createuser(user: user): user = userrepository.createuser(user)     override def createtweet(tweet: tweet): tweet = tweetrepository.createtweet(tweet)     override def getuser(id: string): user = userrepository.getuser(id)     override def gettweet(id: string): tweet = tweetrepository.gettweet(id)     override def getuserandtweets(id: string): (user,list[tweet]) = {       val user = userrepository.getuser(id)       val tweets = tweetrepository.getallbyuser(user)       (user,tweets)     }   } } 

note same spring declaration:

<bean name="usertweetservice" class="service.impl.defaultusertweetservice">     <property name="userrepository" ref="userrepository"/>     <property name="tweetrepository" ref="tweetrepository"/> </bean> 

and when do:

trait myapplicationmixin   extends defaultusertweetservicecomponent   inmemoryuserrepositorycomponent   inmemorytweetrepositorycomponent 

it's same spring declaration (but typesafe application context):

<import resource="classpath*:/meta-inf/application-context-default-tweet-services.xml" /> <import resource="classpath*:/meta-inf/application-context-inmemory-tweet-repository.xml" /> <import resource="classpath*:/meta-inf/application-context-inmemory-user-repository.xml" /> 

then can use app with:

val app = new myapplicationmixin { } 

or

val app = new myapplicationmixin {     override val tweetrepository = mock[tweetrepository] } 

the latter same spring bean override:

<import resource="classpath*:/meta-inf/application-context-default-tweet-services.xml" /> <import resource="classpath*:/meta-inf/application-context-inmemory-tweet-repository.xml" /> <import resource="classpath*:/meta-inf/application-context-inmemory-user-repository.xml" />   <!--   bean override 1 defined in application-context-inmemory-tweet-repository.xml  notice spring isn't helpful declare behavior of mock,   easier cake pattern since directly write code  --> <bean id="tweetrepository" class="repository.impl.mockedtweetrepository"/> 

so come problem, use cake pattern , create service components in application, depend on daorepo trait.

and can do:

trait myapplicationmixin       extends defaultuserservicecomponent       anotherservicecomponent       daorepo 

and then:

val app = new myapplicationmixin { } 

or

val app = new myapplicationmixin {     override val usersdao : users.type = mock[users]     override val anotherdao : another.type = mock[another] } 

once application built can use that:

app.userservice.createuser(...) 

the application built application context


Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -