Scala mocking trait that is extended by another trait - scala

I am trying to test
trait Name extends Helper {
def name() = {
var s = getSystem()
s.name()
}
}
where all I want to do is make sure that the "s.name()" method is invoked once by mocking an instance of s, which is a System.
Helper is defined as so:
trait Helper {
def getSystem() : System = {
systemGetter.get()
}
}
As of now, my NameSpec looks something like:
class NameSpec extends FlatSpec with Matchers with MockitoSugar {
class NameImpl extends Name
var toTest = new NameImpl
val mockSystem = mock[System]
it should "call s.name() once" in {
when(getSystem() is invoked, return a mockSystem)
toTest.name()
// Verify that mockSystem.name() happened only once
}
}
What I'm confused about is how to return a mock System in toTest.name() when it calls getSystem() so that I can verify that the system calls s.name() only once. I could easily mock this System if it were a parameter to the name() method in Name trait, so I guess I don't know how to "inject" a mockSystem to be used instead of a real system when that method is invoked.

Unfortunately your code is not compilable and thus is obviously an inadequate representation of what you really have. Particularly it is not clear how the Helper really gets an object of type System. I think that in the real code you should mock the systemGetter, that I suppose is somehow injected into the objects implementing Helper trait, to return your mockSystem. However it is hard to show you a valid example of that basing on the code you provided. If for some reason this is not what you can do, there are a few more avenues.
You seem to use something like Cake pattern around Helper and its inheritance. If so, you can use a class instead of NameImpl to inject System:
class NameWithInjectedSystem(val system: System) extends Name {
override def getSystem(): System = system
}
it should "call s.name() once" in {
val mockSystem = mock[System]
val nameToTest = new NameWithInjectedSystem(mockSystem)
val mockName = "Mock name"
when(mockSystem.name()).thenReturn(mockName)
val actual = nameToTest.name()
actual should === (mockName)
verify(mockSystem, times(1)).name()
}
Finally you can mock even nameToTest object itself but this is not the way I'd suggest because it binds test to much more implementation details than you should want:
it should "call s.name() once" in {
val mockSystem = mock[System]
val nameToTest = mock[NameImpl]
when(nameToTest.getSystem()).thenReturn(mockSystem)
when(nameToTest.name()).thenCallRealMethod()
val mockName = "Mock name"
when(mockSystem.name()).thenReturn(mockName)
val actual = nameToTest.name()
actual should ===(mockName)
verify(mockSystem, times(1)).name()
}
Note how you must call thenCallRealMethod for the .name() call and so you should do for all the calls inside the name or the test will not work.

Related

Mock new object creation in Scala

I want to write unit test for below scala class.
In the below implementation, QueryConfig is final case class.
class RampGenerator {
def createProfile(queryConfig: QueryConfig): String = {
new BaseQuery(queryConfig).pushToService().getId
}
}
The unit test I have written is this
#RunWith(classOf[JUnitRunner])
class RampGeneratorTest extends FlatSpec with Matchers {
"createProfile" must "succeed" in {
val rampGenerator = new RampGenerator()
val queryConfig = QueryConfig("name", "account", “role")
val baseQuery = mock(classOf[BaseQuery])
val profile = mock(classOf[Profile])
when(new BaseQuery(queryConfig)).thenReturn(baseQuery)
when(baseQuery.pushToService()).thenReturn(profile)
when(profile.getId).thenReturn("1234")
val id = rampGenerator.createProfile(queryConfig)
assert(id.equals("1234"))
}
}
Currently it gives below exception, which is expected, since I don't have mocked class used in when. How do I mock the new instance creation?
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
There are two options:
Use powermockito to mock the constructor (see this question for details)
Externalize object creation
A bit more on the second option - this is actually a testing technique that helps in a variety of situations (a couple of examples: yours, creating akka actors and asserting on hierarchies) - so it might be useful to just have it in the "toolbox".
In your case it'll look something like this:
class RampGenerator(queryFactory: QueryFactory) {
def createProfile(queryConfig: QueryConfig) = queryFactory.buildQuery(queryConfig).pushToService().getId()
}
class QueryFactory() {
def buildQuery(queryConfig: QueryConfig): BaseQuery = ...
}
#RunWith(classOf[JUnitRunner])
class RampGeneratorTest extends FlatSpec with Matchers {
"createProfile" must "succeed" in {
val rampGenerator = new RampGenerator()
val queryConfig = QueryConfig("name", "account", “role")
val queryFactory = mock(classOf[QueryFactory])
val profile = mock(classOf[Profile])
val baseQuery = mock(classOf[BaseQuery])
when(queryFactory.buildQuery(queryConfig)).thenReturn(baseQuery)
when(baseQuery.pushToService()).thenReturn(profile)
when(profile.getId).thenReturn("1234")
val id = rampGenerator.createProfile(queryConfig)
assert(id.equals("1234"))
}
}
Please note query factory does not have to be a separate factory class/hierarchy of classes (and certainly does not require something as heavyweight as abstract factory pattern - although you can use it). In particular, my initial version was just using queryFactory: QueryConfig => BaseQuery function, but mockito cannot mock functions...
If you prefer to inject factory method directly (via function), Scalamock has support for mocking functions

How to test a method by mocking nested methods?

I'm trying to test an Object.method which contains some nested methods from a Trait apart of some calculations. These nested methods have to be mocked (they access to a DB so I want to mock their responses).
When I call the real Object.method, it should skip the nested methods call and retrieve what I want. I've tried mocking them but test is still calling them.
Here's my example source code:
trait MyTrait {
def myMethodToMock(a: String): String
}
object MyObject extends MyTrait {
def myParentMethod(a:String) = {
val b = myMethodToMock(a)
val c = a + b
c
}
}
Then in my test:
val myTraitMock = mock[MyTrait]
when(myTraitMock.myMethodToMock(a)).thenReturn(b)
//Then I call the parent method:
assert(MyObject.myParentMethod(a) equals c)
It throws a NullPointerException as it's still accessing to myMethodToMock
Your code does not compile, so I am going to guess some things of what you are actually trying to do here ...
You are stubbing a method on a mock, and then calling it on a completely unrelated instance. No wonder it does not work.
A good rule of thumb (and the best practice) is to never mock classes you are actually testing. Split everything you want to mock and test separately into a separate class. This is also known as single responsibility principle (each component should be responsible for a single thing).
trait MyTrait {
def myMethodToMock(a: String): String
}
object MyTrait extends MyTrait {
def myMethodtoMock(a: String) = ???
}
class MyObject(helper: MyTrait = MyTrait) {
def myParentMethod(a: String) = a + helper.myMethodToMock(a)
}
object MyObject extends MyObject()
Now, you can write your test like this:
val myTraitMock = mock[MyTrait]
when(myTraitMock.myMethodToMock(any)).thenReturn("b")
new MyObject(myTraitMock).myParentMethod("a") shouldBe "ab"
verify(myTraitMock).myMethodToMock("a")
The main difference here is that you are passing your mock into the object's constructor, so that when it calls the method, it will be the one you stubbed, not the implementation provided by the default class.
You should use composition rather than inheritance, so you can inject an instance of MyTrait that can be a mock or the real one

Testing object which calls another object in Scala using Specs2

I'm working with a project which already has some legacy code written in Scala. I was given a task to write some unit tests for one of its classes when I discovered it's not so easy. Here's the problem I've encountered:
We have an object, say, Worker and another object to access the database, say, DatabaseService which also extends other class (I don't think it matters, but still). Worker, in its turn, is called by higher classes and objects.
So, right now we have something like this:
object Worker {
def performComplexAlgorithm(id: String) = {
val entity = DatabaseService.getById(id)
//Rest of the algorithm
}
}
My first though was 'Well, I can probably make a trait for DatabaseService with the getById method'. I don't really like the idea to create an interface/trait/whatever just for the sake of testing because I believe it doesn't necessarily lead to a nice design, but let's forget about it for now.
Now, if Worker was a class, I could easily use DI. Say, via constructor like this:
trait DatabaseAbstractService {
def getById(id: String): SomeEntity
}
object DatabaseService extends SomeOtherClass with DatabaseAbstractService {
override def getById(id: String): SomeEntity = {/*complex db query*/}
}
//Probably just create the fake using the mock framework right in unit test
object FakeDbService extends DatabaseAbstractService {
override def getById(id: String): SomeEntity = {/*just return something*/}
}
class Worker(val service: DatabaseService) {
def performComplexAlgorithm(id: String) = {
val entity = service.getById(id)
//Rest of the algorithm
}
}
The problem is, Worker is not a class so I can't make an instance of it with another service. I could do something like
object Worker {
var service: DatabaseAbstractService = /*default*/
def setService(s: DatabaseAbstractService) = service = s
}
However, it scarcely makes any sense to me since it looks awful and leads to an object with mutable state which doesn't seem very nice.
The question is, how can I make the existing code easily testable without breaking anything and without making any terrible workarounds? Is it possible or should I change the existing code instead so that I could test it easier?
I was thinking about using extending like this:
class AbstractWorker(val service: DatabaseAbstractService)
object Worker extends AbstractWorker(DatabaseService)
and then I somehow could create a mock of Worker but with different service. However, I didn't figure out how to do it.
I'd appreciate any advice as to how either change the current code to make it more testable or test the existing.
If you can alter the code for Worker, you can change it to still allow it to be an object and also allow for swapping of the db service via an implicit with a default definition. This is one solution and I don't even know if this is possible for you, but here it is:
case class MyObj(id:Long)
trait DatabaseService{
def getById(id:Long):Option[MyObj] = {
//some impl here...
}
}
object DatabaseService extends DatabaseService
object Worker{
def doSomething(id:Long)(implicit dbService:DatabaseService = DatabaseService):Option[MyObj] = {
dbService.getById(id)
}
}
So we set up a trait with concrete impl of the getById method. Then we add an object impl of that trait as a singleton instance to use in the code. This is a good pattern to allow for mocking of what was previously only defined as an object. Then, we make Worker accept an implicit DatabaseService (the trait) on it's method and give it a default value of the object DatabaseService so that regular use does not have to worry about satisfying that requirement. Then we can test it like so:
class WorkerUnitSpec extends Specification with Mockito{
trait scoping extends Scope{
implicit val mockDb = mock[DatabaseService]
}
"Calling doSomething on Worker" should{
"pass the call along to the implicit dbService and return rhe result" in new scoping{
mockDb.getById(123L) returns Some(MyObj(123))
Worker.doSomething(123) must beSome(MyObj(123))
}
}
Here, in my scope, I make an implicit mocked DatabaseService available that will supplant the default DatabaseService on the doSomething method for my testing purposes. Once you do that, you can start mocking out and testing.
Update
If you don't want to take the implicit approach, you could redefine Worker like so:
abstract class Worker(dbService:DatabaseService){
def doSomething(id:Long):Option[MyObj] = {
dbService.getById(id)
}
}
object Worker extends Worker(DatabaseService)
And then test it like so:
class WorkerUnitSpec extends Specification with Mockito{
trait scoping extends Scope{
val mockDb = mock[DatabaseService]
val testWorker = new Worker(mockDb){}
}
"Calling doSomething on Worker" should{
"pass the call along to the implicit dbService and return rhe result" in new scoping{
mockDb.getById(123L) returns Some(MyObj(123))
testWorker.doSomething(123) must beSome(MyObj(123))
}
}
}
In this way, you define all the logic of importance in the abstract Worker class and that's what you till focus your testing on. You provide a singleton Worker via an object that is used in the code for convenience. Having an abstract class let's you use a constructor param to specify the database service impl to use. This is semantically the same as the previous solution but it's cleaner in that you don't need the implicit on every method.

Mockito for Objects in Scala

I'm using Scala 2.10, specs2 and Mockito. I want to mock scala.io.Source.fromURL(). The issue seems to be fromURL() is a function in io.Source's object.
val m = mock[io.Source]
m.fromURL returns io.Source.fromString("Some random string.")
It's a pretty straightforward mock in an Unit test. Why isn't it working?
Thanks!
Instead of mocking it, you could try spying it as follows:
val m = spy(io.Source)
Or you could mock it as follows:
val m = mock[io.Source.type]
But then how are you using Source in the class you are testing? If you had an example class like so:
class MyClass{
def foo = {
io.Source.doSomething //I know doSomething is not on Source, call not important
}
}
Then in order to take advantage of mocking/spying, you'd have to structure your class like so:
class MyClass{
val source = io.Source
def foo = {
source.doSomething
}
}
And then your test would have to look something like this:
val mockSource = mock[io.Source.type]
val toTest = new MyClass{
override val source = mockSource
}
In the Java world, static methods are the bane of mocking. In the Scala world, calls to objects can also be troublesome to deal with for unit tests. But if you follow the code above, you should be able to properly mock out an object based dependency in your class.
Good news! With the latest 1.16 release of mockito-scala, you can now mock scala objects.
To enable withObjectMocked feature, it is mandatory to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
Example:
object FooObject {
def simpleMethod: String = "not mocked!"
}
"mock" should {
"stub an object method" in {
FooObject.simpleMethod shouldBe "not mocked!"
withObjectMocked[FooObject.type] {
FooObject.simpleMethod returns "mocked!"
//or
when(FooObject.simpleMethod) thenReturn "mocked!"
FooObject.simpleMethod shouldBe "mocked!"
}
FooObject.simpleMethod shouldBe "not mocked!"
}
}
See: https://github.com/mockito/mockito-scala#mocking-scala-object
Years later, above answer doesn't work as others have pointed out.
And you cannot mock the scala.io.Source object.
Can I mock final / private methods or classes? This is not supported, as mocks generated with macros are implemented as subclasses of the type to mock. So private and final methods cannot be overridden. You may want to try using an adapter or façade in your code to make it testable. It is better to test against a trait/interface instead of a concrete implementation. There are libraries that support this kind of mocking, such as PowerMock. Be aware that this kind of mocking involves Bytecode manipulation, which has the risk that your test double diverges from the actual implementation.
So what I did is an work around to abstract out scala.io.Source.fromUrl() as a function argument and pass in mocked function in tests.
// original func
def aFuncThatUsesSource() = {
val source = scala.io.Source("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
// test friendly func that accepts `scala.io.Source.fromURL` as arg
def aTestFriendlyFunc(makeApiCall: String => BufferedSource) = {
val source = makeApiCall("127.0.0.1:8080/...")
val result = source.mkString
Try(source.close())
result
}
....
// test spec
def testyMcTesterson = () => {
val makeApiCall = mockFunction[String, BufferedSource]
makeApiCall.expects("something...")
.returns( new BufferedSource(new ByteArrayInputStream("returns something".getBytes)) )
aTestFriendlyFunc(makeApiCall) shouldEqual "returns something"
}

How to log in Scala *without* a reference to the logger in *every instance*?

I've looked at example of logging in Scala, and it usually looks like this:
import org.slf4j.LoggerFactory
trait Loggable {
private lazy val logger = LoggerFactory.getLogger(getClass)
protected def debug(msg: => AnyRef, t: => Throwable = null): Unit =
{...}
}
This seems independent of the concrete logging framework. While this does the job, it also introduces an extraneous lazy val in every instance that wants to do logging, which might well be every instance of the whole application. This seems much too heavy to me, in particular if you have many "small instances" of some specific type.
Is there a way of putting the logger in the object of the concrete class instead, just by using inheritance? If I have to explicitly declare the logger in the object of the class, and explicitly refer to it from the class/trait, then I have written almost as much code as if I had done no reuse at all.
Expressed in a non-logging specific context, the problem would be:
How do I declare in a trait that the implementing class must have a singleton object of type X, and that this singleton object must be accessible through method def x: X ?
I can't simply define an abstract method, because there could only be a single implementation in the class. I want that logging in a super-class gets me the super-class singleton, and logging in the sub-class gets me the sub-class singleton. Or put more simply, I want logging in Scala to work like traditional logging in Java, using static loggers specific to the class doing the logging. My current knowledge of Scala tells me that this is simply not possible without doing it exactly the same way you do in Java, without much if any benefits from using the "better" Scala.
Premature Optimization is the root of all evil
Let's be clear first about one thing: if your trait looks something like this:
trait Logger { lazy val log = Logger.getLogger }
Then what you have not done is as follows:
You have NOT created a logger instance per instance of your type
You have neither given yourself a memory nor a performance problem (unless you have)
What you have done is as follows:
You have an extra reference in each instance of your type
When you access the logger for the first time, you are probably doing some map lookup
Note that, even if you did create a separate logger for each instance of your type (which I frequently do, even if my program contains hundreds of thousands of these, so that I have very fine-grained control over my logging), you almost certainly still will neither have a performance nor a memory problem!
One "solution" is (of course), to make the companion object implement the logger interface:
object MyType extends Logger
class MyType {
import MyType._
log.info("Yay")
}
How do I declare in a trait that the
implementing class must have a
singleton object of type X, and that
this singleton object must be
accessible through method def x: X ?
Declare a trait that must be implemented by your companion objects.
trait Meta[Base] {
val logger = LoggerFactory.getLogger(getClass)
}
Create a base trait for your classes, sub-classes have to overwrite the meta method.
trait Base {
def meta: Meta[Base]
def logger = meta.logger
}
A class Whatever with a companion object:
object Whatever extends Meta[Base]
class Whatever extends Base {
def meta = Whatever
def doSomething = {
logger.log("oops")
}
}
In this way you only need to have a reference to the meta object.
We can use the Whatever class like this.
object Sample {
def main(args: Array[String]) {
val whatever = new Whatever
whatever.doSomething
}
}
I'm not sure I understand your question completely. So I apologize up front if this is not the answer you are looking for.
Define an object were you put your logger into, then create a companion trait.
object Loggable {
private val logger = "I'm a logger"
}
trait Loggable {
import Loggable._
def debug(msg: String) {
println(logger + ": " + msg)
}
}
So now you can use it like this:
scala> abstract class Abstraction
scala> class Implementation extends Abstraction with Loggable
scala> val test = new Implementation
scala> test.debug("error message")
I'm a logger: error message
Does this answer your question?
I think you cannot automatically get the corresponding singleton object of a class or require that such a singleton exists.
One reason is that you cannot know the type of the singleton before it is defined. Not sure, if this helps or if it is the best solution to your problem, but if you want to require some meta object to be defined with a specific trait, you could define something like:
trait HasSingleton[Traits] {
def meta: Traits
}
trait Log {
def classname: String
def log { println(classname) }
}
trait Debug {
def debug { print("Debug") }
}
class A extends HasSingleton[Log] {
def meta = A // Needs to be defined with a Singleton (or any object which inherits from Log}
def f {
meta.log
}
}
object A extends Log {
def classname = "A"
}
class B extends HasSingleton[Log with Debug] { // we want to use Log and Debug here
def meta = B
def g {
meta.log
meta.debug
}
}
object B extends Log with Debug {
def classname = "B"
}
(new A).f
// A
(new B).g
// B
// Debug