Is there a way to tell all methods inside a class to do function call without writing those function calls to every method - scala

I'm coding request calls to tens of services which should be authorized.
I noticed I have written a lot of copy&paste code to the beginning of all methods inside service classes because they all must be authorized before using any services.
Little example...
class AuthorizationService {
val authorized = List("James", "007")
def authorize(user: String) = {
if (!authorized.contains(user)) throw new RuntimeException(s"User '$user' not authorized")
}
}
class Service1 {
val authorizationService = new AuthorizationService
def doThis(user: String) = {
authorizationService.authorize(user)
println(s"User '$user' did this")
}
def doThat(user: String) = {
authorizationService.authorize(user)
println(s"User '$user' did that")
}
}
Now imagine there are 30 service classes with three methods each and I continue to do authorization like the way I have I end up writing 90 functions calls.

Something like this maybe ... It still requires your service to change, but not as much:
object AuthToken {
implicit def auth(s: String)(implicit service: AuthService) = {
service.authorize(s)
AuthToken(s)
}
}
case class AuthToken private[AuthToken] (s: String) {
override def toString = s;
}
class Service1 {
implicit val authorizationService = new AuthorizationService
def doThis(user: AuthToken) = {
println(s"User '$user' did this")
}
}
Now, if you do new Service1().doThis("James"), it will implicitly call your auth service first to convert the name into token.

You could use it like this:
object Tester {
class AuthorizationService {
val authorized = List("James", "007")
def authorize(user: String) = {
if (!authorized.contains(user)) throw new RuntimeException(s"User '$user' not authorized")
}
}
def authorize(businessLogic: => Unit)(implicit
authorizationService: AuthorizationService,
user: String): Unit = {
// authorization logic
authorizationService.authorize(user)
println(s"User '$user' did this")
// actual code that needs to be executed
businessLogic
}
class Service1(implicit val authorizationService: AuthorizationService) {
def doThis(implicit user: String) = authorize {
println("doThis()")
}
def doThat(implicit user: String) = authorize {
println("doThat()")
}
}
def main(args: Array[String]) {
implicit val authorizationService = new AuthorizationService
val s = new Service1()
s.doThat("James")
s.doThat("007")
s.doThat("Neo")
}
}

you could use a crude composition pattern:
class ServiceAuthorizationExecutor {
def call(user: String, delegate: DELGATE_TYPE) = {
authorizationService.authorize(user)
delegate()
}
}

This is a classic AOP problem. The last time I looked at AOP was 12 years ago though, so I'm not sure what the state of it all is.

Related

Mocking scala object called by under another object

I am trying to write unit test for a function under object1.
object Object1 {
def main(sysArgs: Array[String]): Unit = {
val inputDF: DataFrame = UtilObject.getInput()
}
}
object UtilObject {
def getInput(){
...
}
}
To write Unit test, I am using MockitoSugar.
"object1Main" should "should make correct calls" in {
val inputArgs = Array("abc")
val util = mock[UtilObject.type]
when(util.getInput().thenReturn(inputData))
Object1.main(inputArgs)
}
While running the test, it doesn't consider the util mock and just execute the getInput() function.
I think I am missing some sort of injection here. Any ideas?
Thanks in advance!
Mocking Scala objects should be impossible conceptually speaking. An object in Scala is a pure singleton. That means there can only be one member of that type at any time.
mockito-scala can mock Scala objects via reflection. I'll use a result type of String, instead of a DataFrame, but the idea is the same:
object UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String]): String = {
val inputDF: String = UtilObject.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
withObjectMocked[UtilObject.type] {
UtilObject.getInput() returns "mocked!"
Object1.main(inputArgs) shouldBe "mocked!"
}
Object1.main(inputArgs) shouldBe "done"
}
}
This mocks the singleton's method only inside the block of withObjectMocked.
Usually such powerful techniques often tend to be overused or misused, so I don't generally recommend them, unless the design cannot be refactored.
Luckily, yours can: the easiest way is to use Dependency Injection with a class or a function. For DI with a class you require to convert the object being mocked into a class:
class UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String], ut: UtilObject): String = {
val inputDF: String = ut.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
val util = mock[UtilObject]
when(util.getInput()).thenReturn("mocked!")
Object1.main(inputArgs, util) shouldBe "mocked!"
}
}
For DI with a function you need to lift the method you want to mock into a function:
object UtilObject {
def getInput(): String = {
// ...
"done"
}
}
object Object1 {
def main(sysArgs: Array[String], f: () => String = UtilObject.getInput): String = {
val inputDF: String = f()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val inputArgs = Array("abc")
val f = mock[() => String]
when(f()).thenReturn("mocked!")
Object1.main(inputArgs, f) shouldBe "mocked!"
}
}
Since the function takes no arguments, you can convert it into a by-name parameter. I'll leave that to you.
Lastly, another way is to create a trait with the method you want to mock and extend that with the object. But now Object1 requires being a class and have a reference to the object being mocked:
object UtilObject extends Utils {
def getInput(): String = {
// ...
"done"
}
}
trait Utils {
def getInput(): String
}
class Object1 {
val uo: Utils = UtilObject
def main(sysArgs: Array[String]): String = {
val inputDF: String = uo.getInput()
inputDF
}
}
// in test file:
"object1Main" should {
"should make correct calls" in {
val classUnderTest = new Object1 {
override val uo = mock[Utils]
}
val inputArgs = Array("abc")
when(classUnderTest.uo.getInput()).thenReturn("mocked!")
classUnderTest.main(inputArgs) shouldBe "mocked!"
}
}
As you can see, there are a few ways to go. Neither is inherently wrong. It mostly depends on your requirements(e.g. you can't afford adding a dependency just for one UT), needs(e.g. does the object I am testing really needs to be an object or can I make it a class?), guidelines (e.g. your team decided to avoid using powerful testing frameworks that rely on reflection and use DI as much as possible instead) and personal preferences.

How do I compose nested case classes populated with async mongodb queries in play framework

I have been trying to convert mongodb queries I have working with await to using totally async. The problem is, I cannot find any examples or get code working to populate a list of objects where for each object there is a nested find returning futures.
I have seen examples for a single object, such as
val user = mongoDao.getUser(id)
val address = mongoDao.getAddress(user.id)
for that I see for comprehension works just fine. However, I have a list of objects (similar to users) and I cant seem to get the code right.
What I need to do is get all the users in an async manner, then when they complete, get all the addresses and populate a field (or create a new case class.)
val usersFuture : Future[List[User]] = mongoDao.getUsers()
val fullFutures : Future[List[FullUser]] = usersFuture.map(users: List[User] => {
users.map(user: User => {
val futureAddress : Future[Address] = mongoDao.getAddress()
// Now create a object
futureAddress.map(address: Address) {
FullUserInfo(user, address)
}
}
}
So, I'd like to end up with a Future[List[FullUser]] that I can return to the play framework. I've included the cutdown I've tried.
thanks
// OBJECTS HERE
case class Outer(id: Int, name: String)
case class Inner(id: Int, name: String)
case class Combined(id: Int, name: String, inner: Inner)
// FAKE DAO to reproduct
#Singleton
class StatInner #Inject()( implicit val ec: ExecutionContext) {
def outer() = {
Future {
val lb = new ListBuffer[Outer]()
Thread.sleep(1000)
println("Done")
for (id <- 1 to 5) {
lb += Outer(id, s"Hello $id")
}
lb.toList
}
}
def inner(id: Int) : Future[Inner] = {
Future {
Thread.sleep(1000)
Inner(id, s"inner $id")
}
}
}
// CODE to query that is not working
def nestedTree = Action.async {
val statInner : StatInner = new StatInner()
val listouter : Future[List[Outer]] = statInner.outer()
val combined = listouter.map((listOuter : List[Outer]) => {
listOuter.flatMap((outer: Outer) => {
val futInner : Future[Inner] = statInner.inner(outer.id)
futInner.map((inner: Inner) => {
Combined(outer, inner)
})
})
})
combined.map(Json.toJson(_))
}
```
Use Future.{flatMap.sequence}:
val usersFuture: Future[List[User]] = mongoDao.getUsers()
val fullFutures: Future[List[FullUser]] = usersFuture.flatMap { users =>
Future.sequence(users.map { user =>
mongoDao.getAddress().map { adress =>
FullUserInfo(user, address)
}
})
}

Why is the Binding.scala router not reevaluated?

I'm trying to build a generic router for a personal project by Binding.scala.
I've defined a PageState trait
sealed trait WhistState {
def text: String
def hash: String
def render: Binding[Node]
}
with a number of subclasses for each route type. I've then trying to create a router, which based on the hash chooses the correct class.
object Router {
val defaultState: WhistState = DefaultState("Games")
val allStates: Vector[WhistState] = Vector(defaultState)
val route: Route.Hash[WhistState] = Route.Hash[WhistState](defaultState)(new Route.Format[WhistState] {
override def unapply(hashText: String): Option[WhistState] = allStates.find(_.hash == window.location.hash)
override def apply(state: WhistState): String = state.hash
})
route.watch()
}
And then I'm my application classes im trying to use this
object Application {
import example.route.Router._
#dom
def render: Binding[Node] = {
for (hash <- route.state.bind.hash) yield println("hash: " + hash)
route.state.bind match {
case default: WhistState => println("default"); default.render.bind
case _ => println("none"); <div>NotFound</div>
}
}
def main(args: Array[String]): Unit = {
dom.render(document.querySelector("#content"), render)
}
}
I've would expect that changing the hash would force a reevaluation of route.state.bind match ... expression.
Any idea to why this doesn't work?
Best regards
route.state is only changed when unapply returns a Some(newState) and newState does not equal to the previous state.
In your case, unapply always returns Some(defaultState) or None. That's why route.state never changes.

Creating Test Scope/Context to seed data and run application, Scala Play Framework 2

I'm having some trouble figuring out the best way create an easy way to test some of my DB centric application code. Maybe I am skewed from more OO languages, but what I am trying to do is start the application, seed the database, pass seeded data to the test, then clean up the database. I was trying to use before and after blocks, but have been running into all sorts of problem with delayedInit and other race conditions. In the docs you can use the setupData and deleteData, but it doesn't provide an opportunity to pass data to the actual tests. Is there any way this could be achieved?
Here is a sample of the wrapper I am using:
abstract class WithUserData extends WithApplication {
var user = null
override def around[T: AsResult](t: => T): Result = super.around {
setupData()
t
deleteData()
}
def setupData() {
Logger.info("Running Before")
val passwordInfo = PasswordInfo("bcrypt", "$2a$10$at8N/GZHKDbHLh6er.UsbOUjVqx.IGebO2Wc7EmmD2m4tOlin7EAG")
val u = User(new IdentityId("harrypotter#naytev.com", UsernamePasswordProvider.UsernamePassword), "Harry",
"Potter", "Harry Potter", Option("harrypotter#naytev.com"), None, AuthenticationMethod.UserPassword,
None, None, Some(passwordInfo), None, None, "", Subscription.free, None, None, None, List(), None)
User.save(u)
Logger.info(s"Before User is before saving : var ${user} --- variable ${u}")
user = u
Logger.info(s"variable user is ${user}")
}
def deleteData(): Unit ={
Logger.info(s"After User is -> $user")
Logger.info("Removing the user")
User.remove(user)
}
}
Then in my test, I would love to use it like this:
"with wrong password will not allow user to be logged in" in new WithUserData{
Logger.info(s"Running test 1 with User ${user}")
val fakeRequest = FakeRequest(POST, "/authenticate/userpass", FakeHeaders(), "").withFormUrlEncodedBody(("email" , user.email.get), ("password", "Blah"))
val request = route(fakeRequest).get
status(request) must equalTo(BAD_REQUEST)
}
The code above won't work and will give odd errors about user being null, even though the before is being run first. Is there any way for me to pass around a saved user object? I would love to not have to query the object every test. It seems like a lot of boiler plate and should be something handled in before and after.
Any help would be greatly appreciated!
Thanks,
Mike
Loock at http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
You can use something like cake pattern
case class User(id: BigInt, name: String)
trait UserRepositoryComponent {
def userLocator: UserLocator
trait UserLocator {
def getUser: User
def removeUser(user: User)
}
}
trait UserTestRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserTestLocator
class UserTestLocator extends UserLocator {
override def getUser: User = User(1, "test user")
override def removeUser(user: User): Unit = ()
}
}
trait UserRealRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserRealLocator
class UserRealLocator extends UserLocator {
override def getUser: User = User(1, "real user")
override def removeUser(user: User): Unit = ()
}
}
trait UserServiceComponent {
this: UserRepositoryComponent =>
def getUser: User = userLocator.getUser
def removeUser(user: User) = userLocator.removeUser(user)
}
trait WithUserData {
this: UserServiceComponent =>
println(getUser)
}
object Main extends App {
val userDataFake: WithUserData = new WithUserData with UserServiceComponent with UserTestRepositoryComponent
val userDataReal: WithUserData = new WithUserData with UserServiceComponent with UserRealRepositoryComponent
}
Or somthing like http://docs.scala-lang.org/tutorials/tour/implicit-parameters.html

I18n in Play Framework 2.4.0

Here is my routes file:
GET /:lang controller.Application.index(lang: String)
GET /:lang/news controller.Application.news(lang: String)
Note that all of them start with /:lang.
Currently, I write Application.scala as
def index(lang: String) = Action {
implicit val messages: Messages = play.api.i18n.Messages.Implicits.applicationMessages(
Lang(lang), play.api.Play.current)
Ok(views.html.index("title"))
}
In this way, I have to write as many implicit Messages as Action. Is there any better solution for this?
Passing just Lang is simpler option:
def lang(lang: String) = Action {
Ok(views.html.index("play")(Lang(lang)))
}
//template
#(text: String)(implicit lang: play.api.i18n.Lang)
#Messages("hello")
You can reuse some code by using action composition, define wrapped request and action:
case class LocalizedRequest(val lang: Lang, request: Request[AnyContent]) extends WrappedRequest(request)
def LocalizedAction(lang: String)(f: LocalizedRequest => Result) = {
Action{ request =>
f(LocalizedRequest(Lang(lang), request))
}
}
Now you are able to reuse LocalizedAction like this:
//template
#(text: String)(implicit request: controllers.LocalizedRequest)
#Messages("hello")
//controller
def lang(lang: String) = LocalizedAction(lang){implicit request =>
Ok(views.html.index("play"))
}
Finally, I solved this problem in the following way.
As #Infinity suggests, I defined wrapped request and action as:
case class LocalizedRequest(messages: Messages,
request: Request[AnyContent])
extends WrappedRequest(request)
object Actions {
def LocalizedAction(lang: String)(f: LocalizedRequest => Result) = {
Action { request =>
f(LocalizedRequest(applicationMessages(Lang(lang), current), request))
}
}
object Implicits {
implicit def localizedRequest2Messages(implicit request: LocalizedRequest): Messages = request.messages
}
}
Now I'm able to use LocalizedAction like this:
def lang(lang: String) = LocalizedAction(lang) { implicit request =>
Ok(views.html.index("play"))
}
However, in order to omit the implicit parameter of Messages, which should be a play.api.i18n.Messages, I added a line to my template as:
#import controllers.Actions.Implicits._