Scala: Why using self-type instead of mixin produces stackoverflow? - scala

trait UserRepository {
def findByFirstName(firstName: String): Seq[User]
}
trait UserBusinessDelegate extends UserRepository {
abstract override def findByFirstName(firstName: String) = {
super.findByFirstName(firstName)
}
}
class MockUserRepository extends UserRepository {
override def findByFirstName(firstName: String) = {
// whatever
}
}
val userRepository = new MockUserRepository with UserBusinessDelegate
userRepository.findByFirstName("John") // OK
However, if I change UserBusinessDelegate as follows:
trait UserBusinessDelegate {
self: UserRepository =>
override def findByFirstName(firstName: String): Seq[User] = {
self.findByFirstName(firstName) // requires explicit return type, thinks this is a recursive call
}
}
val userRepository = new MockUserRepository with UserBusinessDelegate
userRepository.findByFirstName("John") // StackOverflow!!!
I understand stackable pattern and hence how the first case works. My question is why the 2nd doesn't.

In the second snippet you have a recursive call without an exit condition:
override def findByFirstName(firstName: String): Seq[User] = {
self.findByFirstName(firstName)
}
This will always call findByFirstName from UserBusinessDelegate (because you're using self, which basically says that this object will have this kind of behaviour at runtime, not that it's parent will have it and therefore we should call parent's method) creating a new stack frame with each call -> stack overflow.
In the second snippet UserBusinessDelegate's findByFirstName will be called and then you call MockUserRepository's method from it using super -> no recursion -> no stack overflow. You can check Scala's stackable trait pattern for more info.
#Edit: to make it more clear, in the snippet that throws a SO exception the findByFirstName method from MockUserRepository won't be called because you are overriding it in UserBusinessDelegate therefore the anonymous class created with new MockUserRepository with UserBusinessDelegate will only contain the overriden method and that's why the SO, is that clear?
Why would you assume that the method from MockUserRepository would get invoked?
#Edit2: the code doesn't compile without override because self: UserRepository => tells the compiler that a method with such a signature will already be there at runtime and you cannot have 2 methods with the same signature. The first example works only because it's a stackable trait, such traits are dynamically bound and can modify the behaviour but have to call super at some point (which normally isn't allowed without the abstract override modifier, I really recommend going through the link I posted about stackable pattern).
Maybe someone else knows a way, from what I know there's no way to call the mock method unless you change the method name in UserBusinessDelegate and drop the override, then you can call self.findByFirstName and it will call the method from MockUserRepository.

Related

Scala: Want to implement the function to be called before each method of the same class(something like #before implementation))

Is there a way to invoke a function by default before any other function in a class is called?
I do not want to use frameworks and want to implement in pure Scala.
What I wanted to do is have some function in a class which checks if a user has access to the called method when a method of the same class is called.
This is done in a straightforward way with a private constructor, custom apply and companion object.
case class Foo private (bar: Bar){
def methYouWantToCall: Unit = ???
}
object Foo {
def apply(bar: Bar): Foo = {
val foo = new Foo(bar)
foo.methYouWantToCall
foo
}
}
Hence methYouWantToCall should be sideffecting function with Unit return type.
As you use scala, there are plenty of means of avoiding such ones.

Is it possible to mock a Scala implicit class?

I can extend my Scala class Foo with additional methods via an implicit class:
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
But can I mock out those methods?
import org.mockito.Mockito
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
import FooExtensions.implicits._
val foo = mock[Foo]
Mockito.when(foo.baz).thenReturn("bix") // fails at runtime
}
}
}
This compiles, but fails with
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Is it possible to mock methods added via implicit classes? Hopefully with Mockito (or mockito-scala) but I'm interested in any approach that works.
Thing about extension methods, is that they are basically a syntactic sugar:
trait Foo
implicit class ExtensionMethods(foo: Foo) {
def bar: String = "bar
}
foo.bar
is equal to
new ExtensionMethods(foo).bar
So mocking:
Mockito.when(foo.bar).thenReturn("bix")
becomes:
Mockito.when(new ExtensionMethods(foo).bar).thenReturn("bix")
I think there is no workaround - perhaps PowerMock could let you change class constructor..., but with normal Mockito it is impossible.
Usually, it is not a problem though. That is because either:
you put into extension methods behavior, that only depends on extended value and passed parameters (and extended method is quite often pure function that doesn't require mocking) - if you want to change something there, you change input,
if behavior should change, you implement it inside a type class, and make extension method use that type class to inject behavior
trait Bar {
def bar: String
}
object Bar {
implicit val defaultBar: Bar = new Bar { def bar = "bar" }
}
implicit class ExtensionMethods(foo: Foo) {
def bar(implicit bar: Bar): String = bar.bar
}
// in test
implicit var overridenBar: Bar = ...
assert(foo.bar === "sth")
On a side note: the more functional you'll get the less you'll need to mock things as everything will depend only on input passed inside, and a cascade of mocks will become just a code smell - too tight coupling, too large interfaces, etc. Problem is that many Java libraries do not even follow SOLID principles, which makes them both hard to use/test with FP as well as bad OOP on its own. I'm telling this in case you feel mocking is the only way to go in your case.
The only way to achieve that is to use implicit conversions rather than implicit classes
This is a hack intended to show how this could be achieved, but I'd urge to take a look at the code and see why you actually need to do this
So, following your example, you could modify the code to look like this
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit fooToOps(foo: Foo): FooOps = new FooOps(foo)
class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
and your test
import org.scalatest.WordSpec
import org.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
val fooOps = mock[FooOps]
implicit fooToOps(foo: Foo): FooOps = fooOps
val foo = mock[Foo]
when(foo.baz) thenReturn "bix" // works
}
}
}
the other thing to consider is that in your production you need to get an implicit parameter of the shape Foo => FooOps so when you call that method from the test the actual implicit mock is provided...
As I said, you can make it work like this, but I agree with Mateusz that you shouldn't need to

How can I call a super class method from a code block in a derived class?

This question is somewhat hard to summarize. Following code block shows what I want to do.
I have a base class like this:
`class Base {
def methA:String="ook"
def methB:Int=1
}
Also I have a derived class, where I want each subclass method to call the super class method twice, compare the results and throw an exception on mismatch (this is for a test scenario).
But if I write
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super[Derived].methB)
}
}
Then this will not compile. The only way out of this problem sofar has been to extract a method in class Derived which only calls the superclass' methB and to call this from the lambda call.
Is there a better way?
I understood you want to call super call method. Hope below is what you want.
You can call that as below with the key word super only
(new Derived).methB . This will call super call method in callDoublyAndCompare twice as per your code .
class Derived extends Base {
private def callDoublyAndCompare[T](fun:()=>T) : T = {
val fst=fun()
val snd=fun()
if(fst!=snd) throw new RuntimeException(s"Mismatch fst=$fst != snd=$snd")
snd
}
override def methB:Int={
callDoublyAndCompare(() => super.methB) //kept only super
}
}
The original example was not fully complete insofar as the Derived class was defined as inner class of another scala class.
After I moved out this inner class to the top level, the example from Praveen above suddenly worked.

Scala typeclass pattern and covariance

We've got several types of resources and we wanted to make a method to check if a resource is healthy or not. Given that the type of resources are very heterogeneous we didn't want to use standard subclassing and we decided to use a typeclass:
trait CanHealthCheck[T] {
def isHealthy(t: T): Boolean
}
We also have a utility method to be able to check if a given resource is alive/healthy or not
object LivenessChecker {
def isAlive[T](t: T)(implicit canHealthCheck: CanHealthCheck[T]): Boolean = {
canHealthCheck.isHealthy(t)
}
}
We've got a repository layer to access to the data. We would like to express the idea that a given abstract repository must be "health checkable" but to leave the implementation details to the subclasses implementing the trait:
trait UserRepository {
def findSomeUser(): User = ???
implicit def isHealthCheckable: CanHealthCheck[UserRepository]
}
The problem arises when we want to subclass UserRepository with a particular implementation, given that CanHealthCheck is not covariant on the type T.
class DbUserRepository extends UserRepository {
def ping: Boolean = ???
override implicit val isHealthCheckable: CanHealthCheck[UserRepository] =
new CanHealthCheck[DbUserRepository] {
def isHealthy(db: DbUserRepository) = db.ping
}
}
And this is an example of some dummy function that acts on the abstract repository while trying to check if the repository is alive:
def someDummyFunction(userRepository: UserRepository) = {
if(LivenessChecker.isAlive(userRepository)) // This won't compile
userRepository.findSomeUser()
}
The idea is that our application uses the UserRepository trait and not the implementation, and thus we cannot check whether the repository is alive or not. How can we continue using the repository abstraction layer and be able to check if a given (abstract) repository is alive? Is the typeclass pattern the correct pattern to use here?
There is something a bit fishy with isHealthCheckable inside UserRespository. The isHealthy method, when called, would have two instances of UserRepository available: of course, the one passed as the t argument, but also, the UserRepository.this of the enclosing instance.
This is a sign of something wrong. Either the method should be written somewhere else, so that it does not get enclosing this, or it should not get the argument
That second option is consistent with using UserRepository the object-oriented, subtyping way. Also, it is consistent with your idea that every UserRepository must be heath-checkable. Just do
trait UserRepository {
...
def isHealty: Boolean
}
It is fine to call that directly, userDirectory.isHealthy. But you can then also easily implement the type class:
object UserRepository {
implicit val canHealthCheck = new CanHealthCheck[UserRepository] {
def isHealthy(repository: UserRepository) = repository.IsHealthy
}
}
also note that it was not clear at all how the implicit instance method would have come into the implicit scope. With the companion object, it works fine.
Use "type bounds".
I couldn't test this, but to get the code to compile, you could do something like:
class DbUserRepository[U <: UserRepository] extends UserRepository {
def ping: Boolean = ???
implicit val isHealthCheckable: CanHealthCheck[U] =
new CanHealthCheck[U] {
def isHealthy(db: U) = db.ping
}
}

implementing methods of traits with additional implicit parameters

I want an object to implement the trait Iterable and pass an additional implicit parameter to the implemented method:
object MyRepository extends Iterable[Something] {
def iterator(implict entityManager: EntityManager): Iterator[Something] = ...
}
Obviously this doesn't work because the iterator method has no implicit parameter and is hence not implemented by the method shown above.
An example use case is the map method which I want to apply to the repository values:
def get = Action {
Transaction { implicit EntityManager =>
val result = MyRepository.map(s => s ...)
}
}
Is there some way to implement the Iterable trait and capture the implicit pramameter?
Given that Iterable.iterator does not have this implicit in its signature, you cannot expect to be able to implement this method while adding this implicit: that would be another method (specifically, another overload).
However, if MyRepositorywas a class rather than an object, you could capture the implicit in the class constructor.
And if you want to keep the same use style (as in MyRepository.map{ ... } rather than new MyRepository.map{ ... }), what you can do is to provide an implicit conversion from the object to the class.
Here is an example:
object MyRepository {
class MyRepositoryIterable(implicit entityManager: EntityManager) extends Iterable[Something] {
def iterator: Iterator[Something] = ???
}
implicit def toIterable(rep: MyRepository.type)(implicit entityManager: EntityManager): MyRepositoryIterable = new MyRepositoryIterable
}
What happens now when you do MyRepository.map(...) is that the object gets implicitly converted into an instance of MyRepositoryIterable which captures the implicit EntityManager value. The MyRepositoryIterable is the class that actually implements Iterable.