Scala: How can I mock this function using Mockito? - scala

I am wanting to test one of my akka actors, it uses slick to get the information from the database. In my actor I have this bit of code
CardStationPermissions.retrieveByStationID(stationID).foreach(card => {
I want to know how can I mock that function to change the output instead of relaying on whats in the database?

It's really difficult to mock things that are being called in a static way (in this case, a call on an object as opposed to an instance of a class). When you need to be able to mock and test things like this, I tend to agree with Mustafa's suggestion that creating a trait to represent the relevant methods to mock. A simple example would look as follows:
case class MyObject(id:Long)
trait MyDao{
def getData(input:String):List[MyObject] = ...
}
object MyDao extends MyDao
class MyActor extends Actor{
val myDao:MyDao = MyDao
def receive = {
case param:String => sender ! myDao.getData(param)
}
}
Here you can see that I have a trait to represent my dao methods (only 1 for this example) and then I mix that trait into a scala object as the default instantiation of that trait. When I setup my dao in my actor, I explicitly type it to the trait so that I can substitute a mock impl of that trait later.
So then if I wanted a simple test showing mocking, it could look something like this (via specs2):
class MyActorTest(_system:ActorSystem) extends TestKit(_system)
with Specification with Mockito with ImplicitSender{
def this() = this(ActorSystem("test"))
trait scoping extends Scope{
val mockDao = mock[MyDao]
val actor = TestActorRef(new MyActor{
override val myDao = mockDao
})
}
"A request to get data" should{
"pass the input to the dao and return the result to the sender" in new scoping{
mockDao.getData("foo") returns List(MyObject(1))
actor ! "foo"
expectMsg(List(MyObject(1)))
}
}
}

Related

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.

Mixins with Akka

I have an actor to which I want inject dependency using mixin. Code:
trait ProductsAware {
def getProducts: List[Product]
}
trait MyActor extends Actor with ProductsAware {
val products = getProducts
...
}
As you can see I'm just trying to decouple MyActor from concrete instance of ProductsAware trait, and provide concrete instance in other place (when creating actor).
And this is concrete implementation of ProductsAware trait:
trait ProductsAwareFirstImpl {
override def getProducts = {List(new Product())}
}
And I want to create new MyActor and inject to MyActor this concrete implementation ProductsAwareFirstImpl:
system.actorOf(Props[MyActor])
The problem is that is not safe at compile time, i.e. anyone can forget to mix the ProductsAwareFirstImplto MyActor
You can use a different Actor Props construction technique, namely the Props(new Actor) as documented here. Just make sure you are careful and not closing over any state, e.g. putting it in a object and calling it via a method should be safe. This is described in the documentation, but a quick mockup would look like this:
object MyActor {
def newActorWithFirstImpl = new MyActor with ProductsAwareFirstImpl
}
//...
system.actorOf(Props(MyActor.newActorWithFirstImpl))
To be sure that some trait is mixed to you actor you may user explicit self type reference:
trait MyActor extends Actor {
self: ProductsAware =>
val products = getProducts
// ...
}
So no one could instantiate MyActor without mixin ProductsAware

Abstracting the Database client in the cake pattern

I am trying to create an abstraction for a SearchService using the Cake pattern. This is what I have currently:
trait SearchServiceComponent{
val searchService:SearchService
trait SearchService{
def searchForSomething(..):List[String]
def updateIndex(..):Boolean
}
}
Lets say I have a DbSearchServiceComponent and LuceneSearchServiceComponent as follows:
trait DbSearchServiceComponent extends SearchServiceComponent{
class DbSearchService extends SearchService{
//Initialize the db client
//Implement all the trait methods
}
}
Similarly...
trait LuceneSearchServiceComponent extends SearchServiceComponent{
class LuceneSearchService extends SearchService{
//Initialize the lucene client
//Implement all the trait methods
}
}
The issue I have with the above snippet is that
I have initialized instances of lucene client and the db client in the Service implementations.
Ideally I would want to "mix-in" a "Client" base type that can be either a Db client or a Lucene client but I am pretty confused as to how to inject a polymorphic client type here.
Can somebody point out how I may be able to refactor the code so that I can inject different versions of the client to my implementations of the SearchService trait?
Not sure if I interpret your question correctly, but that's how you could use the cake pattern for this:
trait SearchServiceComponent {
val searchService: SearchService
trait SearchService {
def searchForSomething(...): List[String]
def updateIndex(...): Boolean
}
}
trait DbSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
trait trait LuceneSearchServiceComponent extends SearchServiceComponent {
override val searchService = new SearchService {
// Initialize client, implement methods
}
}
and upon instantiation:
val myLucenceApp = new Whatever with LuceneSearchServiceComponent
val myDbApp = new Whatever with DbSearchServiceComponent
where Whatever would typically be something along the lines of
class Whatever { this: SearchServiceComponent =>
// ... use `searchService` and do lots of other things
}

How to mix in traits with implicit vals of the same name but different types?

I have traits from two third party libraries that I'm trying to mix in to my own trait. They both define implicit vals named log.
However, they are of different types - one is an SLF4J Logger, the other is a Spray LoggingContext (which is really an Akka LoggingAdapter). In fact the second trait is from Spray, it's an HttpServer. (Not the most recent version you can find on Github which no longer has that val).
So, here's the code (library one renamed because it's proprietary, the Spray code snipped to show just relevant part):
object LibraryOneShim {
trait LibraryOne {
implicit val log: org.slf4j.Logger = ...
}
}
// https://github.com/spray/spray/blob/a996a5b6bdd830e613583fed86e87bf049fdb8c0/spray-routing/src/main/scala/spray/routing/HttpService.scala
trait HttpService extends Directives {
val log = LoggingContext.fromActorRefFactory // this is a LoggingContext/LoggingAdapter
}
trait MyTrait extends HttpService with LibraryOne {
val myRoute = ...
}
class MyActor extends Actor with MyTrait {
def receive = runRoute(myRoute)
}
This won't compile. The compiler complains:
error: overriding lazy value log in trait HttpService of type
java.lang.Object with spray.util.LoggingContext; lazy value log in
trait LibraryOne$class of type org.slf4j.Logger needs `override'
modifier trait DemoService extends HttpService with LibraryOne {
Is there any way I can mix in these two traits together?
As far as I can tell the only way is to create a CombinedLogger
class CombinedLogger(l1:Logger, l2:LoggingAdapter) extends Logger with LoggingAdapter {
// proxy methods to the correct logger
}
If both loggers were declared as def you could use it like this:
override def log = new CombinedLogger(super[LibraryOne].log, super[HttpService].log)
In this case it's tricky because they are defined as val which tell the Scala compiler they are a single value that will not change. And because of that it will not allow you to call super.log. So you would need to copy the logic of the overridden traits.
The other tricky part in this case is that you would need to proxy 50+ methods in the CombinedLogger.