How can I use MockitoSugar to mock an object (singleton) method? - scala

Is there a way in scala to use MockitoSugar in order to mock a method of an object that is a scala singleton?

Your best bet to deal with singletons for mocking is to first do a little rework on the structure of the singleton itself. Use a trait to define the operations and then have the object extend the trait like so:
trait Fooable{
def doFoo:String = "foo"
}
object Foo extends Fooable
Then, in any class that needs the Foo object, declare it as an input or something that can be set (DI), but decalare it as the trait instead like this:
class MyFooUser(foo:Fooable = Foo){
}
That way by default it uses the object, but when constructing for your tests, you can give it a mocked Fooable instead. There are a bunch of ways to handle getting the Fooable into your classes (this is one) and that's not really in scope for this answer. The answer really is about using a trait first to define the methods and then having the object extend that trait and then referring to it as the trait in any class that needs it. That will allow you to mock it effectively.

Mockito won't help with objects, but you can try to use ScalaMock instead.

Related

What are the advantages or disadvantages of declaring function/method in companion objects versus declaring them in traits?

I am new to Scala and I now started a project in Scala and I see similar to the following construct:
trait SomeTrait extends SomeOtherStuff with SomeOtherStuff2
object SomeTrait {
def someFunction():Unit = { ??? }
}
I understand that for a class, companion objects hold methods that are used in a "static", like Factory methods in Java or something alike, but what about traits, why not put these methods in traits?
The first style is called mixin, it used to be somewhat popular back in the days.
It could be replaced by the following code:
object SomeOtherStuff {
def someMethod(): String
}
object SomeObj {
import SomeOtherStuff._
//now someMethod is available
def otherMethod(): String = someMethod + "!"
}
object Caller {
import SomeObj._
import SomeOtherStuff._
//utility methods from both objects are available here
}
Pros of mixins:
If SomeTrait extends 10 other mixins then extending this trait would allow to scrap 10 import statements
Cons of mixins:
1) creates unnecessary coupling between traits
2) awkward to use if the caller doesn't extend the mixin itself
Avoiding mixins for business-logic code is a safe choice.
Although I'm aware of 2 legitimate usecases:
1) importing DSLs
e.g. ScalaTest code :
class SomeSuite extends FunSuite with BeforeAndAfter {...}
2) working (as a library author) with implicit parameters:
e.g. object Clock extends LowPriorityImplicits
(https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/Clock.scala#L127)
Another perspective to this is the OOP principle Composition Over Inheritance.
Pros of companion objects (composition):
composition can be done at runtime while traits are defined at compile time
you can easily have multiple of them. You don't have to deal with the quirks of multiple inheritance: say you have two traits that both have a method with the name foo - which one is going to be used or does it work at all? For me, it's easier to see the delegation of a method call, multiple inheritance tends to become complex very fast because you lose track where a method was actually defined
Pros of traits (mixins):
mixins seem more idiomatic to reuse, a class using a companion object of another class is odd. You can create standalone objects though.
it's cool for frameworks because it adds the frameworks functionality to your class without much effort. Something like that just isn't possible with companion objects.
In doubt, I prefer companion objects, but it always depends on your environment.

Choosing between Trait and Object

I was trying to look into trait and object in scala when it seems like we can use trait and object to do a similar task.
What should be the guiding principles on when to use trait and when to use object?
Edit:
As many of you are asking for an example
object PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
trait PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
There is a Process class which can use the object
object Process {
def doSomething(df: DataFrame): DataFrame {
PercentileStats.addPercentile(df)
}
}
We can also make it use the trait
object Process with PercentileStats {
def doSomething(df: DataFrame): DataFrame {
addPercentile(df)
}
}
I think the real question here is Where do I put stand-alone functions?
There are three options.
In the package
You can put stand-alone functions in the outer package scope. This makes them immediately available to the whole package but the name has to be meaningful across the whole package.
def addPercentile(df: DataFrame): DataFrame // implementation
In an object
You can group stand-alone functions in an object to provide a simple namespace. This means that you have to use the name of the object to access the functions, but it keeps them out of the global namespace and allows the names to be simpler:
object PercentileStats {
def add(df: DataFrame): DataFrame // implementation
}
In a trait
You can group stand-alone functions in a trait. This also removes them from the package namespace, but allows them to be accessed without a qualifier from classes that have that trait. But this also makes the method visible outside the class, and allows them to be overridden. To avoid this you should mark them protected final:
trait PercentileStats {
protected final def addPercentile(df: DataFrame): DataFrame // implementation
}
Which is best?
The choice really depends on how the function will be used. If a function is only to be used in a particular scope then it might make sense to put it in a trait, otherwise the other options are better. If there are a number of related function then grouping them in an object makes sense. One-off functions for general use can just go in the package.
Object - is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.
As a top-level value, an object is a singleton.
Traits - are used to share interfaces and fields between classes.
Classes and objects can extend while traits cannot be instantiated and therefore have no parameters.
So, it means that if you prefer singleton type implementation with no new instance happen then use Object but if you want to inherit implementation to other class or objects then you can use trait.
Traits: are equivalent to interfaces in Java. So you can use it to define public contracts like interfaces in Java. In addition, a trait can be used to share values (beside methods) between classes extends the trait.
Objects in Scala is actually quite flexible. Example use cases include:
singletons: If you think that your objects are singletons (exactly
one instance exists in the program), you can use object.
factory: for instance, companion object of a class can be used as factory for creating instances of the class.
to share static methods: for example, common utilities can be declared in one object.
You also have to consider how you would want to use / import it.
trait Foo {
def test(): String
}
object Bar extends Foo
import Bar._
Objects enable you to import rather than mix in your class.
It is a life saver when you want to mock - with scalamock - a class that mixes a lot of traits and expose more than 22 methods that you don't really need exposed in the scope.

What does it mean when object extends class with no implementation

object PostgresDriver extends PostgresDriver
I see this in slick with no implementation whatsoever. I am wonder does that just automatically create a singleton class?
This is pretty standard practice, defining a trait to represent the abstraction and then providing a standard implementation of that trait as an object. If you just do it as the object you don't have an abstraction to refer to it as and stuff like that can make mocking and testing difficult at the least

Scala generic: require method to use class's type

I'm pretty new to Scala. I'm trying to write an abstract class whose methods will be required to be implemented on a subclass. I want to use generics to enforce that the method takes a parameter of the current class.
abstract class MySuper{
def doSomething:(MyInput[thisclass]=>MyResult)
}
class MySub extends MySuper{
override def doSomething:(MyInput[MySub]=>MyResult)
}
I know that thisclass above is invalid, but I think it kind of expresses what I want to say. Basically I want to reference the implementing class. What would be the valid way to go about this?
You can do this with a neat little trick:
trait MySuper[A <: MySuper[A]]{
def doSomething(that: A)
}
class Limited extends MySuper[Limited]{
def doSomething(that: Limited)
}
There are other approaches but I find this one works fairly well at expressing what you'd like.

Why do people define object extends its companion class?

I find this kind of code is very common in Lift framework, written like this:
object BindHelpers extends BindHelpers {}
What does this mean?
In this case, BindHelpers is a trait and not a class. Let foo() to be a method defined in BindHelpers, to access it you can either.
Use it through the companion object: BindHelpers.foo()
Mix the trait BindHelpers in a class and thus be able to access the methods inside of it.
For instance:
class MyClass extends MyParentClass with BindHelpers {
val a = foo()
}
The same techniques is used in Scalatest for ShouldMatchers for instance.
You can find David Pollak's answer to the same question in the liftweb group.
It's interesting for an object to extend its companion class because it will have the same type as the class.
If object BindHelpers didn't extend BindHelpers, it would be of type BindHelpers$.
It might be that the pattern here is other. I don't know Lift to answer this, but there's a problem with object in that they are not mockable. So, if you define everything in a class, which can be mocked, and then just makes the object extend it, you can mock the class and use it instead of the object inside your tests.