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.
Related
I'm trying to build a function that takes a generic case class, but I want to insure that the passed parameter is indeed a case class.
Searching has turned up only things about inheritance with self defined case classes but not about generic case classes. A guaranteed, messier, way of doing this is to use reflection to run a check on the passed case class object before do things. If it is not a case, throw an exception:
def handleCaseClass[A](caseClass:A):Unit = {
val isCaseClass = // use reflection to check
if (isCaseClass) { /*do work */ } else { throw invalidArgumentException }
}
This could get a little messy, but not a big deal. I was wondering if there was a cleaner way by using type bounds, but I've searched around and can't find anything of the like:
def handleCaseClass[A <: ???](caseClass:A):Unit = {
/* do work */
}
Is anything like this possible? Also, what would be best practices?
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.
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.
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.
I have a trait, named Init:
package test
trait Init {
def init(): Any
}
There are some classes and an object, extends this trait:
package test
object Config extends Init {
def init() = { loadFromFile(...) }
}
class InitDb extends Init {
def init() = { initdb() }
}
When app has started, I will find all classes and objects which extends Init, and invoke their init method.
package test
object App {
def main(args: Array[String]) {
val classNames: List[String] = findAllNamesOfSubclassOf[Init]
println(classNames) // -> List(test.Config$, test.InitDb)
classNames foreach { name =>
Class.forName(name).newInstance().asInstanceOf[Init].init() // ***
}
}
}
Please note the "*" line. For test.InitDb, it's OK. But for test.Config$, when newInstance(), it throws an exception said we can't access its private method.
My problem is, how to get that object, and run its init method?
There's usually little point to doing this in Scala. Just put some code in the body of any object and it'll be executed when that object is first initialised, saving you the nasty performance hit of pre-initialising everything.
In general though, finding all subclasses of a particular type requires a full classpath scan. There are a few libraries to do this, but one of the more common is Apache's commons-discover
However... This is dynamic code, it uses reflection, and it's really NOT idiomatic. Scala has sharper tools than that, so please don't try and swing the blunt ones with such violence!
I don't totally agree with Kevin. There are some exceptions. For example I wrote a Scala desktop app. I split the core and the modules into two parts. At startup time the core loads all modules into GUI. At that time the core just gets the name of modules, it doesn't need to initialize something. Then I put all module's init code in an init() function. That function will be called when user executes the module.
#Freewind: About reflection in Scala, it's absolutely the same in Java. Just please note that the methods from Java which are used with reflection, are used for Java objects - not Scala. I'm sorry for my English. I mean those methods can not work with Scala object, trait.
For example:
var classLoader = new java.net.URLClassLoader(
Array(new File("module.jar").toURI.toURL),
/*
* need to specify parent, so we have all class instances
* in current context
*/
this.getClass.getClassLoader)
var clazz = classLoader.loadClass("test.InitDb")
if (classOf[Init].isAssignableFrom(clazz))
var an_init = clazz.newInstance.asInstanceOf[Init];
But you can not do it the opposite way:
if (clazz.isAssignableFrom(classOf[Init]))
Because Init is a trait, and Java method isAssignableFrom(Class) doesn't know trait.
I'm not sure if my question is useful for you, but here it is.