ScalaMock Inheritied Trait Function of Object ScalaTest - scala

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.

Related

Scala mock not mocking extended class function?

Here is how the code looks:
class B {
doStuff() //some API call
}
class A extends B {
val x = doStuff()
...
}
When I mock it as follows:
class ASpec {
val a = new A
when(a.doStuff()).thenReturn("stuff") <---this should just return "stuff" on the test
assert(true, a.doOtherStuff())
}
Problem is that its definitely still making the API call from doStuff(). How come its not returning "stuff" as specified?
You need to make A a mock. Right now, you're creating a real instance of A via new A. Instead, use mock(classOf[A]) (or, with ScalaTest's MockitoSugar, mock[A]):
val a = mock(classOf[A])
when(a.doStuff()).thenReturn("stuff")
when(a.doOtherStuff()).thenCallRealMethod() // Necessary since `A` is a mock
assert(a.doOtherStuff())
However, it's generally a Bad Idea™ to mock one method of a class so that you can test another. For one thing, you'll need to remember to specify the behavior of each method of A used by doOtherStuff (potentially using thenCallRealMethod on all of them). Prefer only mocking things external to your class. To accomplish this, you can either mock what doStuff depends on or move doStuff to another class.

Scala unit testing - stubbing a singleton

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) = { ??? }

Generating a Scala class automatically from a trait

I want to create a method that generates an implementation of a trait. For example:
trait Foo {
def a
def b(i:Int):String
}
object Processor {
def exec(instance: AnyRef, method: String, params: AnyRef*) = {
//whatever
}
}
class Bar {
def wrap[T] = {
// Here create a new instance of the implementing class, i.e. if T is Foo,
// generate a new FooImpl(this)
}
}
I would like to dynamically generate the FooImpl class like so:
class FooImpl(val wrapped:AnyRef) extends Foo {
def a = Processor.exec(wrapped, "a")
def b(i:Int) = Processor.exec(wrapped, "b", i)
}
Manually implementing each of the traits is not something we would like (lots of boilerplate) so I'd like to be able to generate the Impl classes at compile time. I was thinking of annotating the classes and perhaps writing a compiler plugin, but perhaps there's an easier way? Any pointers will be appreciated.
java.lang.reflect.Proxy could do something quite close to what you want :
import java.lang.reflect.{InvocationHandler, Method, Proxy}
class Bar {
def wrap[T : ClassManifest] : T = {
val theClass = classManifest[T].erasure.asInstanceOf[Class[T]]
theClass.cast(
Proxy.newProxyInstance(
theClass.getClassLoader(),
Array(theClass),
new InvocationHandler {
def invoke(target: AnyRef, method: Method, params: Array[AnyRef])
= Processor.exec(this, method.getName, params: _*)
}))
}
}
With that, you have no need to generate FooImpl.
A limitation is that it will work only for trait where no methods are implemented. More precisely, if a method is implemented in the trait, calling it will still route to the processor, and ignore the implementation.
You can write a macro (macros are officially a part of Scala since 2.10.0-M3), something along the lines of Mixing in a trait dynamically. Unfortunately now I don't have time to compose an example for you, but feel free to ask questions on our mailing list at http://groups.google.com/group/scala-internals.
You can see three different ways to do this in ScalaMock.
ScalaMock 2 (the current release version, which supports Scala 2.8.x and 2.9.x) uses java.lang.reflect.Proxy to support dynamically typed mocks and a compiler plugin to generate statically typed mocks.
ScalaMock 3 (currently available as a preview release for Scala 2.10.x) uses macros to support statically typed mocks.
Assuming that you can use Scala 2.10.x, I would strongly recommend the macro-based approach over a compiler plugin. You can certainly make the compiler plugin work (as ScalaMock demonstrates) but it's not easy and macros are a dramatically superior approach.

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.

How do I mock static function (Object function, not class function) in scala

Object A {
def a = { something}
}
// I've import A, but still have error message: not found: type A
val x = mock[A]
You don't. Not only A is not a type or class -- it is an instance -- but it is an instance of a singleton (A.type).
What you do instead is put your methods on a trait, and make the object extend it. Then, you mock the trait instead of mocking the object.
You may find this email thread instructive.
Whilst pure mocking of the object is not possible with any tool yet, the thread above does have a few options for you. All of which involve changing your design to some degree.