Scala unit testing - stubbing a singleton - scala

I'm new to unit testing in Scala and I can't find a way to stub a function defined in a singleton object.
For example:
class Profile {
def getLatest
...
Feed.getLatestEntries
...
}
object Feed {
def getLatestEntries: Future[List[FeedEntry]] { /* Access some API*/ }
}
I'm trying to unit test the getLatest function defined in the Profile class.
Since I don't want to actually access an external API through the web in my unit tests I'm trying to stub the Feed object and its getLatestEntries function to return some predefined value.
I've looked into the ScalaMock, EasyMock and Mockito frameworks but could not find a way to stub a method of a singleton object. ScalaMock states
How come all the mocking frameworks do not offer this functionality? How can I do this? stub Feed.getLatestEntries ?
Thanks

My approach has been to create the logic of the singleton as a trait and then have the object extend the trait. This allows me provide the Singleton as a default or implicit argument, but provide a stubbed out implementation for testing
trait FeedLogic {
def getLatestEntries: Future[List[FeedEntry]] { /* Access some API*/ }
}
object Feed extends FeedLogic
def somethingWantingFeed(...)(feed: FeeLogic = Feed) = { ??? }

Related

Check if Scala class is instance of T

My application handles a lot of third party integrations. I have an abstract base class for third party integrations which specifies a bunch of methods that an integration class should handle – then certain integrations can be extended with additional functionality that is not available on all integrations.
Basically it looks like this:
abstract class Integration { ... }
trait SingleSignOn { ... }
class NormalIntegration extends Integration {}
class SingleSignOnIntegration extends Integration with SingleSignOn {}
I would like to be able to sort out all integrations that have a specific trait, and this is what I thought of as the basic solution:
val allIntegrations: Seq[Integration] = ...
def integrationsWithTrait[T]: Seq[Integration] = {
allIntegrations.filter(_.isInstanceOf[T])
}
The usage is:
val singleSignOnIntegrations = integrationsWithTrait[SingleSignOn]
The issue is that isInstanceOf[T] always returns true (meaning I end up with singleSignOnIntegrations == allIntegrations), while hard coded isInstanceOf[SingleSignOn] works as intended.
How do I fix integrationsWithTrait to work as I intend?
This will work:
def integrationsWithTrait[T](implicit tag: scala.reflect.ClassTag[T]): Seq[Integration] = {
allIntegrations.filter(tag.runtimeClass.isInstance)
}
Scalac will inject ClassTag instance for every class that this method will be called with. This will allow to access the Class object in runtime and verify if the class is the instance of given class/trait.
I think the original code doesn't work because of type erasure.

ScalaMock Inheritied Trait Function of Object ScalaTest

I am attempting to test a function, however the function that I am testing makes a call to the traits function which I would like to stub. I can't seem to stub this function using ScalaMock, as I am unable to mock the object.
trait[A<:CommonReturn] commonTrait[A] {
def commonFunction(s:String):(String,String) = {
("Hello","World")
}
def testMe(s:String) : A
}
This trait is then extended by many Objects each implementing commonTrait and returning their specific sub-type of common return.
object ob extends commonTrait[ConcreteType] {
override def testMe(s:String){
val(x,y) = commonFunction(s)
val z = "unique logic"
ConcreteType(x,y,z)
}
}
I therefore am now trying to test ob.testMe however I can't seem to Mock the ob Object, therefore can't stub the commonFunction.
Is this due to my architecture? Or is it possible to mock an object with scalamock and use scalatest?
val mocked = mock[ob]
(mocked.commonFunction _).expect(*).returning("test","test")
This doesn't compile.
you cannot mock objects with ScalaMock, as a mock[X] is a subclass of X. Scala does not allow subclasses of objects.
If you need to test collaboration with this commonFunction then inheritance makes it rather difficult. I would consider designing this with Dependency Injection instead.

Best Practice to Load Class in Scala

I'm new to Scala (and functional programming as well) and I'm developing a plugin based application to learn and study.
I've cretead a trait to be the interface of a plugin. So when my app starts, it will load all the classes that implement this trait.
trait Plugin {
def init(config: Properties)
def execute(parameters: Map[String, Array[String]])
}
In my learning of Scala, I've read that if I want to program in functional way, I should avoid using var. Here's my problem:
The init method will be called after the class being loaded. And probably I will want to use the values from the config parameter in the execute method.
How to store this without using a var? Is there a better practice to do what I want here?
Thanks
There is more to programming in a functional way than just avoiding vars. One key concept is also to prefer immutable objects. In that respect your Plugin API is already breaking functional principles as both methods are only executed for their side-effects. With such an API using vars inside the implementation does not make a difference.
For an immutable plugin instance you could split plugin creation:
trait PluginFactory {
def createPlugin (config: Properties): Plugin
}
trait Plugin {
def execute ...
}
Example:
class MyPluginFactory extends MyPlugin {
def createPlugin (config: Properties): Plugin = {
val someValue = ... // extract from config
new MyPlugin(someValue)
}
}
class MyPlugin (someValue: String) extends Plugin {
def execute ... // using someConfig
}
You can use a val! It's basically the same thing, but the value of a val field cannot be modified later on. If you were using a class, you could write:
For example:
class Plugin(val config: Properties) {
def init {
// do init stuff...
}
def execute = // ...
}
Unfortunately, a trait cannot have class parameters. If you want to have a config field in your trait, you wont be able to set its value immediately, so it will have to be a var.

scala: strategy to define mock objects, injecting dependencies using implicits

I have a Social object, responsable of connecting to Twitter, facebook, etc, and retrieve provider info for the specified user
For each provider I implemented a singleton TwitterAdapter, all inheriting from an abstract class SocialAdapter
here's the code: https://github.com/RestOpenGov/ideas-ba/blob/master/webservice/app/services/security/SocialConnector.scala#L98
For testing, I would obviously like to mock the TwitterAdapter, so that instead of connecting with twitter it returns some fixed response.
One solution I've found was to inject the list of adapters using an implicit parameter. The problem with this solution is that the Social.retrieveSocialProviderInfo is called from other functions, so I have to pass around the implicit List[SocialAdapter] parameter though all the call chain, like this:
def createApplicationToken(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], ApplicationToken] = {
// go to social info provider and fetch information
retrieveProviderInfo(accessToken).fold(
[...]
def retrieveProviderInfo(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters)
: Either[List[Error], IdentityProviderInfo] = {
[...]
and finally
object Social {
val defaultAdapters = List(TwitterAdapter, FacebookAdapter)
def retrieveSocialProviderInfo
(accessToken: AccessToken)
(implicit adapters: List[SocialAdapter] = Social.defaultAdapters) // adapters can be injected
: Option[IdentityProviderInfo] = {
[...]
You get the idea
It works fine, normally I just ignore the second group of parameters and pick the default from Social.defaultAdapters, I only set it to List(MockTwitterAdapter, MockFacebookAdapter) when testing, but I'm cluttering the code just to be able to test it.
The other solution would be to make Social.defaultAdapters a var (instead of a val) and just change it for testing, normally in production mode it would always have the same value.
I think this must be a pretty common scenario. Is there a better strategy to handle these situations? Or maybe some way to extend the scope of the implicit assignment? Or shall I just go with a full-featured dependency injection framework?
A simple approach can be to just use traits all along:
// you can test this trait and override the adapters as you wish
// by overriding the defaultAdapters member
trait Social {
implicit val defaultAdapters = List(TwitterAdapter, FacebookAdapter)
def retrieveSocialProviderInfo(accessToken: AccessToken):
Option[IdentityProviderInfo] = ...
}
// you can use this object directly in your production code
// if you don't want to mix it in
object Social extends Social
// or use the trait by mixing it with another
trait Application extends Social {
def createApplicationToken(accessToken: AccessToken):
Either[List[Error], ApplicationToken] = {
// the defaultAdapters are accessible to the
// retrieveProviderInfo method
retrieveProviderInfo(accessToken).fold(...)
}

Scala Mock Object Creation

Is there a way to create an object of a given type that overrides a subset of methods and throws runtime exceptions for the rest of the methods?
It doesn't even need to have access to any implementation of the superclass. It just needs to have the same type at compiletime and runtime.
That pretty much is what a ScalaMock mock object does out of the box — methods you've set expectations on do whatever the expectations tell them to do, all others throw an ExpectationException.
What's your use-case?
As Paul said, ScalaMock is a good way to go.
But I wanted to point out that you're just describing basic inheritance:
class OriginalClass {
def methodToRun() = { println("called OriginalClass.methodToRun") }
def methodNotToRun() = { println("called OriginalClass.methodNotToRun") }
}
class MockOriginalClass extends OriginalClass {
override def methodToRun() = super.methodToRun()
override def methodNotToRun() = throw new RuntimeException("you weren't supposed to run this!")
}
Then, in your code, where you were expecting an OriginalClass object you can pass in a MockOriginalClass and it will throw errors when you call the wrong things.