public
Last active

Using cake pattern in Play 2.0

  • Download Gist
play-2.0-cake.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
// my response to https://groups.google.com/forum/?fromgroups#!searchin/play-framework/cake/play-framework/LQ2y40QNZaE/qvRFw5of-rQJ
 
import play.api._
import play.api.mvc._
 
// Domain object
case class User(id: String, name: String)
 
// Trait defining the service component
trait UserServiceComponent {
trait UserService {
def getUserName(id: String): String
}
 
val userService: UserService
}
 
// Real implmentation
trait RealUserServiceComponent extends UserServiceComponent {
 
// Explicit dependency on User Repository
self: UserRepositoryComponent =>
 
override val userService: UserService = new UserService {
// Use the repository in the service
override def getUserName(id: String) = userRepository.getUser(id).name
}
}
 
// Trait defining the repository
trait UserRepositoryComponent {
trait UserRepository {
def getUser(id: String): User
}
 
val userRepository: UserRepository
}
 
// Real implmentation of repository
trait RealUserRepositoryComponent extends UserRepositoryComponent {
override val userRepository: UserRepository = new UserRepository {
override def getUser(id: String) = error("todo") // i.e to database, etc.
}
}
 
// Fake implmentation of the repository
trait MockUserRepositoryComponent extends UserRepositoryComponent {
override val userRepository: UserRepository = error("todo") // i.e. mock[UserRepository]
}
 
 
// Both of these "environments" are just mixins of the component traits.
// Therefore, they have as member variables all services and dependencies.
// All dependencies are compile checked - if a mixin is needed but not provided, the code won't compile.
 
// "Real" top level environment usable in controllers.
object real extends RealUserServiceComponent with RealUserRepositoryComponent
 
// "Fake" top level environment usable in controllers.
object fake extends RealUserServiceComponent with MockUserRepositoryComponent
 
// Use the real environment in the top level controller
object Application extends Controller {
 
val userService = real userService
 
def name(id: String) = Action {
Ok(userService.getUserName(id))
}
 
}
 
// Use the fake environment in the test.
class SomeTest {
 
val userService = fake userService
 
def sometTest {
// set up the mock ...
val name = userService.getUserName("id1")
// do assertion
}
}
 
// Or you can define the components add hoc.
class SomeOtherTest extends RealUserServiceComponent with UserRepositoryComponent {
override val userRepository = error("todo") // mock or something
 
def someOtherTest {
// set up the mock
val name = userService.getUserName("id2")
// do assertion
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.