Skip to content

Instantly share code, notes, and snippets.

@mrcmatuszak
Last active November 24, 2016 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrcmatuszak/b94d3ae5041968c170ea20d9c833bebf to your computer and use it in GitHub Desktop.
Save mrcmatuszak/b94d3ae5041968c170ea20d9c833bebf to your computer and use it in GitHub Desktop.
case class User(id: Long, name: String)
/**
Następujący scenariusz
UserService zależy od UserRepository. UserRepository wyciąga dane np z bazy.
Kilka przypadków
1. UserService zależy bezpośrednio od UserRepository (który jest klasą)
2. UserService zależy od AbstractUserRepository (który jest traitem)
3. Każda operacja z UserRepository jest wyciągnięta do oddzielnego traita (z superclass UserRepository) i UserService zależy od
triatów z niezależnymi operacjami
Założenia
1. UserRepository zależy od połączenia do bazy i też przyjmuje jakiś argumenty
2. UserService wykonuje więcej niż tylko delegowanie do repository
*/
// Atomowe operacje wyciągnięte do traitów
trait AbstractUserFind {
val findUser: Long => User
}
trait AbstractUserCreate {
val createUser: Long => String => User
}
trait AbstractUserUpdate {
val updateUser: Long => String => User
}
// java-style abstract repository (dao)
trait AbstractUserRepository { //albo extends AbstractUserFind with ...
val findUser: Long => User
val createUser: Long => String => User
val updateUser: Long => String => User
}
// implementacja
trait /* or class*/ UserRepository //tu jest trait, żeby przypadek z self-type się skompilował, zazwyczaj spotyka się class
extends AbstractUserRepository
with AbstractUserFind
with AbstractUserCreate
with AbstractUserUpdate {
override val findUser: Long => User = id => User(id, "name")
override val createUser: Long => String => User = id => name => User(id, name)
override val updateUser: Long => String => User = id => name => findUser(id).copy(name = name)
}
trait abstract_field {
trait UserService {
def repository: UserRepository
def findUser(id: Long): User = repository.findUser(id)
}
class UserServiceImpl {
val repository = new UserRepository {}
}
object TestCase {
val mockRepo = new UserRepository {
override val findUser: Long => User = id => User(id, "name") //potrzebujemy tylko tej metody do testu, ale musimy mockować pozostałe
override val createUser: Long => String => User = id => name => User(id, name)
override val updateUser: Long => String => User = id => name => findUser(id).copy(name = name)
}
val service = new UserService {
override val repository = mockRepo
}
service.findUser(1L) == User(1L, "name")
}
}
trait self_type {
trait UserService {
self: UserRepository =>
}
class UserServiceComponent extends UserService with UserRepository
//podobnie jak wyżej musimy dostarczyć implementacje wszystkich metod
}
trait field {
class UserService(repo: UserRepository) {
def findUser(id: Long): User = repo.findUser(id)
}
}
trait def_param {
class UserService {
def createUser(id: Long, name: String)(finder: AbstractUserCreate): User = finder.createUser(id)(name)
def findUser(id: Long)(find: Long => User): User = find(id)
}
object UserServiceTest {
val service = new UserService
def assertUser = {
val repo: Long => User = id => User(id, "name")
service.findUser(1L)(repo) == User(1, "name")
}
}
object UserServiceTest2 {
val service = new UserService
def assertUser = {
val repo = new AbstractUserCreate {
val createUser: Long => String => User = id => name => User(id, name)
}
service.createUser(1L, "name")(repo) == User(1L, "name")
}
}
{
val service = new UserService
val repo = new UserRepository { }
val user = service.findUser(1L)(repo.findUser)
}
{
val service = new UserService
val repo = new UserRepository { }
val user = service.createUser(1L, "name")(repo)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment