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.
Related
In this Scala class
class A{
def a() = {b();}
def b() = {...}
}
If I want to test a(), is it possible to mock or stub b()
Mocks override all methods (usually with return null unless explicitly stated to return something else) while here you want to override just one method. Since your class isn't final it would be easier to do something like
val tested: A = new A {
override def b = ...
}
than mock it (actually mocking final classes is also impossible without something like PowerMock)
val tested = mock[A]
(tested.b _) returning (...)
// tested.a returns null and ignores b
because mock would also override a making your tests useless. You could "fix" it by mocking a to have the same implementation as the original... but this is absurd for many reasons.
So mocking method of a tested class with a mocking framework is possible but it's getting in the way rather than helping.
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.
I have the following setup:
trait A
{
def doSomething(): Unit;
}
object B extends A
{
override def doSomething(): Unit =
{
// Implementation
}
}
class B(creator: String) extends A
{
override def doSomething(): Unit =
{
B.doSomething() // Now this is just completely unnecessary, but the compiler of course insists upon implementing the method
}
}
Now you may wonder why I even do this, why I let the class extend the trait as well.
The problem is, that somewhere in the Program there is a Collection of A.
So somewhere:
private val aList: ListBuffer[A] = new ListBuffer[A]
and in there, I also have to put Bs (among other derivates, namely C and D)
So I can't just let the B-class not extend it.
As the implementation is the same for all instances, I want to use an Object.
But there is also a reason I really need this Object. Because there is a class:
abstract class Worker
{
def getAType(): A
def do(): Unit =
{
getAType().doSomething()
}
}
class WorkerA
{
def getAType(): A =
{
return B
}
}
Here the singleton/object of B gets returned. This is needed for the implementation of do() in the Worker.
To summarize:
The object B is needed because of the generic implementation in do() (Worker-Class) and also because doSomething() never changes.
The class B is needed because in the collection of the BaseType A there are different instances of B with different authors.
As both the object and the class have to implement the trait for above reasons I'm in kind of a dilemma here. I couldn't find a satisfying solution that looks neater.
So, my question is (It turns out as a non-native-speaker I should've clarified this more)
Is there any way to let a class extend a trait (or class) and say that any abstract-method implementation should be looked up in the object instead of the class, so that I must only implement "doSomething()" (from the trait) once (in the object)? As I said, the trait fulfills two different tasks here.
One being a BaseType so that the collection can get instances of the class. The other being a contract to ensure the doSomething()-method is there in every object.
So the Object B needs to extend the trait, because a trait is like a Java interface and every (!) Object B (or C, or D) needs to have that method. (So the only option I see -> define an interface/trait and make sure the method is there)
edit: In case anyone wonders. How I really solved the problem: I implemented two traits.
Now for one class (where I need it) I extend both and for the other I only extend one. So I actually never have to implement any method that is not absolutely necessary :)
As I wrote in the comment section, it's really unclear to me what you're asking.
However, looking at your code examples, it seems to me that trait A isn't really required.
You can use the types that already come with the Scala SDK:
object B extends (()=>Unit) {
def apply() { /* implementation */ }
}
Or, as a variant:
object B {
val aType:()=>Unit = {() => /* implementation */ }
}
In the first case, you can access the singleton instance with B, in the second case with B.aType.
In the second case, no explicit declaration of the apply method is needed.
Pick what you like.
The essential message is: You don't need a trait if you just define one simple method.
That's what Scala functions are for.
The list type might look like this:
private val aList:ListBuffer[()=>Unit] = ???
(By the way: Why not declare it as Seq[()=>Unit]? Is it important to the caller that it is a ListBuffer and not some other kind of sequence?)
Your worker might then look like this:
abstract class Worker {
def aType:()=>Unit // no need for the `get` prefix here, or the empty parameter list
def do() {aType()}
}
Note that now the Worker type has become a class that offers a method that invokes a function.
So, there is really no need to have a Worker class.
You can just take the function (aType) directly and invoke it, just so.
If you always want to call the implementation in object B, well - just do that then.
There is no need to wrap the call in instances of other types.
Your example class B just forwards the call to the B object, which is really unnecessary.
There is no need to even create an instance of B.
It does have the private member variable creator, but since it's never used, it will never be accessed in any way.
So, I would recommend to completely remove the class B.
All you need is the type ()=>Unit, which is exactly what you need: A function that takes no parameters and returns nothing.
If you get tired of writing ()=>Unit all the time, you can define a type alias, for example inside the package object.
Here is my recommentation:
type SideEffect = ()=>Unit
Then you can use SideEffect as an alias for ()=>Unit.
That's all I can make of it.
It looks to me that this is probably not what you were looking for.
But maybe this will help you a little bit along the way.
If you want to have a more concrete answer, it would be nice if you would clarify the question.
object B doesn't really have much to do with class B aside from some special rules.
If you wish to reuse that doSomething method you should just reuse the implementation from the object:
class B {
def doSomething() = B.doSomething()
}
If you want to specify object B as a specific instance of class B then you should do the following:
object B extends B("some particular creator") {
...
}
You also do not need override modifiers although they can be handy for compiler checks.
The notion of a companion object extending a trait is useful for defining behavior associated with the class itself (e.g. static methods) as opposed to instances of the class. In other words, it allows your static methods to implement interfaces. Here's an example:
import java.nio.ByteBuffer
// a trait to be implemented by the companion object of a class
// to convey the fixed size of any instance of that class
trait Sized { def size: Int }
// create a buffer based on the size information provided by the
// companion object
def createBuffer(sized: Sized): ByteBuffer = ByteBuffer.allocate(sized.size)
class MyClass(x: Long) {
def writeTo(buffer: ByteBuffer) { buffer.putLong(x) }
}
object MyClass extends Sized {
def size = java.lang.Long.SIZE / java.lang.Byte.SIZE
}
// create a buffer with correct sizing for MyClass whose companion
// object implements Sized. Note that we don't need an instance
// of MyClass to obtain sizing information.
val buf = createBuffer(MyClass)
// write an instance of MyClass to the buffer.
val c = new MyClass(42)
c.writeTo(buf)
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.
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.