0

I am new to entire ecosystem including Scala, Akka and ScalaTest

I am working on a problem where my Actor gives call to external system.

case object LogProcessRequest

class LProcessor extends Actor {
  val log = Logging(context.system, this)

  def receive = {
    case LogProcessRequest =>
      log.debug("starting log processing")
      LogReaderDisruptor main(Array())
  }
}

The LogReaderDisruptor main(Array()) is a Java class that does many other things.

The test I have currently looks like

class LProcessorSpec extends UnitTestSpec("testSystem") {

  "A mocked log processor" should {
    "be called" in  {
      val logProcessorActor = system.actorOf(Props[LProcessor])
      logProcessorActor ! LogProcessRequest
    }
  }
}

where UnitTestSpec looks like (and inspired from here)

import akka.actor.ActorSystem
import akka.testkit.{ImplicitSender, TestKit}
import org.scalatest.matchers.MustMatchers
import org.scalatest.{BeforeAndAfterAll, WordSpecLike}

abstract class UnitTestSpec(name: String)
  extends TestKit(ActorSystem(name))
  with WordSpecLike
  with MustMatchers
  with BeforeAndAfterAll
  with ImplicitSender {

  override def afterAll() {
    system.shutdown()
  }
}

Question

  • How can I mock the call to LogReaderDisruptor main(Array()) and verify that it was called?

I am coming from Java, JUnit, Mockito land and something that I would have done here would be

doNothing().when(logReaderDisruptor).main(Matchers.<String>anyVararg())
verify(logReaderDisruptor, times(1)).main(Matchers.<String>anyVararg())

I am not sure how to translate that with ScalaTest here.

Also, This code may not be idiomatic, since I am very new and learning

daydreamer
  • 87,243
  • 191
  • 450
  • 722

1 Answers1

0

There are a few ways to do this. The kind of OO way is to wrap logDisrupter as an object and pass it in. I would set up a companion object to instantiate the actor. Something like below. Then you can pass alternate implementation. You can also achieve a similar approach by using traits and mixing in an alternative logDisrupter only as needed.

object LProcessor {
   def props(logDisrupter : LogDisrupter) = Props(new LProcessor(logDisrupter))
}

class LProcessor(logDisrupter : LogDisrupter) extends Actor {
  val log = Logging(context.system, this)

  def receive = {
    case LogProcessRequest =>
      log.debug("starting log processing")
      logDisrupter.doSomething();
  }
}

Then instatiate as

val logProcessorActor = system.actorOf(LProcessor.props(logDisrupter))
Lionel Port
  • 3,492
  • 23
  • 26
  • This sounds like an excellent advice. This is however challenging in my scenario since `LogDisrupter.main` is a `static` method in `Java` class that is a dependent library – daydreamer May 27 '15 at 01:55
  • Can't you wrap it in an object. e.g. class LogDisrupterWrapper { def doSomething = LogDisrupter.main } and pass around the wrapper. – Lionel Port May 27 '15 at 04:47