Scala Testing: Replace function implementation - scala

Using ScalaTest, I want to replace a function implementation in a test case. My use case:
object Module {
private def currentYear() = DateTime.now().year.get
def doSomething(): Unit = {
val year = currentYear()
// do something with the year
}
}
I want to write a unit test testing Module.doSomething, but I don't want this test case to depend on the actual year the test is run in.
In dynamic languages I often used a construct that can replace a functions implementation to return a fixed value.
I'd like my test case to change the implementation of Module.currentYear to always return 2014, no matter what the actual year is.
I found several mocking libraries (Mockito, ScalaMock, ...), but they all only could create new mock objects. None of them seemed to be able to replace the implementation of a method.
Is there a way to do that? If not, how could I test code like that while not being dependent on the year the test is run in?

One way would be to just make do_something_with_the_year accessible to your test case (make it package protected for example). This is also nice because it separates looking up dependencies and actually using them.
Another way would be to put your logic in a trait, make the currentYear method protected and let the object be an instance of that trait. That way you could just create a custom object out of the trait it in a test and wouldn't need any mock library.

ScalaMock can mock singleton objects it says it right here: http://paulbutcher.com/2011/11/06/scalamock-step-by-step/
As well as traits (interfaces) and functions, it can also mock:
Classes
Singleton and companion objects (static methods) ...

Related

Mocking case classes as properties of an object

Consider a case class:
case class configuredThing[A, B](param: string) {
val ...
def ...
}
Test code was able to be partially written for configuredThing which has some methods on it that make some external calls to other services.
This case class is used elsewhere:
object actionObject {
private lazy val thingA = configuredThing[A, B]("A")
private lazy val thingB = configuredThing[C, D]("B")
def ...
}
Here the types A, B, C, and D are actually specified and are not native scala types but defined in a third party package we are leveraging to interface with some external services.
In trying to write tests for this object the requirement is to not have the external calls made so as to test the logic in actionObject. This lead to looking into how to mock out configuredThing within actionObject to be able to make assertions on the different interactions with the configuredThing instances. However, it is unclear how to do this.
In looking at scalatest's scalamock documentation this would need to be done with the Generated mocks system which states "rely on the ScalaMock compiler plugin". However, this seems to have not been released since scala 2.9.2, see here.
So, my question is this: how can this be tested?

Scala Argument Capture of External Class

So I want to check arguments that I send to an external class that I do not control. The external class is assumed tested, I simply want to test if I passed it the right parameters. I have tried some combination of ArgumentCaptor etc, but not much luck
import org.ABC.ExternalClass
case class Foo(i:Int, j: Int...) {
val EC = CreateExternalClass()
def CreateExternalClass(): ExternalClass = {
new ExternalClass (i, j, ....many parameters)
}
}
I think you are getting things wrong here: you can only use an ArgumentCaptor on calls to mocked objects. You can't use them to "intercept" arbitrary calls between all kinds of objects.
Meaning: you could only use an ArgumentCaptor if you would be using a mocked ExternalClass object. But then you would not need to capture, as you probably could do simply method call argument verification.
But of course, you can't use Mockito to mock that call to new in your production class. The options you have:
Turn to PowerMockito or JMockit; frameworks that allow to mock calls to new. Not recommended.
Rework your production code to not do that call to new. Probably not helpful here; as this class might already be a wrapper around that external class
Go for checking on the created object: check if you could use getter methods to simply query the newly created object to have the values that you expect to show up inside

Use mocked function return value in real function call

Is it possible to use a mocked function inside a real function call? Both functions are in the same object. So for example, if I have
obj A {
def mockThis(value: Int): Int = {
value*5
}
def realFuncIWantToTest(value: Int): Int = {
val v = mockThis(value)
v
}
}
Obviously this is an extremely simple case and this isn't what my code is doing (v is actually a complicated object). Essentially I want realFuncIWantToTest to use the mocked function return value that I define.
Thanks!
You might be able to do this using Mockito's spies; see here for an example on that.
Spies basically work by having that spy wrapping around a real object of your class under test.
But one word here: even when it is possible, please consider changing your design instead. This "partial mocking" is often a good indication that your class is violating the single responsibility principle. Meaning: a class should be responsible for "one" thing. But the idea that you can / have to partially mock things within your class indicates that your class is responsible for at least two, somehow disconnect aspects.
In that sense: the better approach would be that mockThis() would be a call on another object; which could be inserted via dependency injection into this class.
Long story short: at least on a Java level your idea should work fine (where I have certain doubts that Mockito will work nicely with your scala objects) from a technical perspective; but from a conceptual point point; you should rather avoid doing it this way.

Override a method in a mock object

I need to write a unit test in which one of the dependencies of the tested object will be mocked. In that mocked object I would like to override one function (I do not care about the other functions at all).
What I need to do, is to provide a completely new implementation of that function. I am not particularly happy with providing mockito-style when / thenResult pairs for each potential input, i.e. I do not want to write:
when(mock.foo(5)).thenResult(3)
when(mock.foo(7)).thenResult(121)
...
I would rather like to write something like:
mock.foo = (a: Int) => if (a == 5) 3 else ...
Which mocking framework should I choose to substitute the whole implementation of a function in an easy way?
You don't need a mocking framework at all if you're only overriding one method and want to do it by actually defining the method.
If it's a class, just extend your class, override the method and inject your extension.
If it's an object or a final class of course you can't extend, but then you wouldn't be able to mock with many frameworks either, or inject an alternate easily.
http://scalamock.org/user-guide/advanced_topics/
See "onCall" method
(fooMock.increment _) expects(*) onCall { arg: Int => arg + 1}

Scala v 2.10: How to get a new instance of a class (object) starting from the class name

I have tens of JSON fragments to parse, and for each one I need to get an instance of the right parser. My idea was to create a config file where to write the name of the class to instantiate for each parser (a kind of map url -> parser) . Getting back to your solution, I cannot call the method I implemented in each parser if I have a pointer to Any. I suppose this is a very common problem with a well-set solution, but I have no idea what the best practices could be.
I really have no experience with Java, Reflection, Class Loading and all that stuff. So,
can anyone write for me the body of the method below? I need to get an instance of a class passed as String (no arguments needed for the constructor, at least so far...)
def createInstance(clazzName: String) = {
// get the Class for the given clazzName, e.g. "net.my.BeautifulClazz"
// instantiate an object and return it
}
Thanks, as usual...
There is a very simple answer:
scala> def createInstance(clazzName: String) = Class.forName(clazzName).newInstance
createInstance: (clazzName: String)Any
scala> createInstance("java.lang.String")
res0: Any = ""
If it works for you, everything is fine. If it don't, we have to look into your class loader. This is usually the point when things will get dirty.
Depending in what you want to do, look into:
The cake pattern, if you want to combine your classes during compile time
OSGi when you want to build a plugin infrastructure (look here for a very simple example)
Google guice, if you really need dependency injection (e.g. when mixing Scala and Java code) and the cake pattern does not work for you