MockitoExtension doesn't init mocks for scala tests - scala

I am using #ExtendWith(Array(classOf[MockitoExtension])) in test class that extends FlatSpec, And my tests failed because my mocks don't initialized between the test (Both from IntelliJ and sbt test) I am sure I am doing something wrong but I am not sure what...
Here is my code:
#ExtendWith(Array(classOf[MockitoExtension]))
class Mytests extends FlatSpec with MockitoSugar with ReadFuture with BeforeAndAfter {
private val myMockcache = mock[...]
val underTest = new testClass(myMockcache)
it should "return result with error if myMockcache.invalidateIfPresent throw exception" in {
when(myMockcache.invalidateIfPresent(..., ...)).thenThrow(ex)
readFuture(underTest.doSomthing(...)) shouldBe ItemResult(None, error = Some(ex))
}
it should "update the cache" in {
readFuture(underTest.doSomthing(...)) shouldBe ItemResult(Some(...), error = None)
}
}
I am using mockito-junit-jupiter-2.28.2
Thanks

Related

Unit test a controller with AssetsFinder dependency in Play Framework

I have a controller that looks like:
class LoginController #Inject()(cc: ControllerComponents)
(implicit ec: ExecutionContext, assetsFinder: AssetsFinder)
I would like to write a unit test for that controller, but I need something to mock the assetsFinder dependency:
class LoginControllerSpec extends PlaySpec with Results with GuiceOneAppPerSuite {
"something to test" should {
"behave as expected" in {
val controller = new LoginController(stubControllerComponents())(???)
}
}
}
How can I mock that dependency?
You can try something like:
class LoginControllerSpec extends PlaySpec with Results with GuiceOneAppPerSuite with MockitoSugar {
"something to test" should {
"behave as expected" in {
val mockControllerComponents = mock[ControllerComponents]
implicit val mockAssetsFinder = mock[AssetsFinder]
implicit val ec = scala.concurrent.ExecutionContext.global
val controller = new LoginController(mockControllerComponents)
// asserts here
}
}
}
MockitoSugar was part of scalatest up to version 3.0.8 . If you are using a newer version, you need to import:
"org.scalatestplus" %% "mockito-3-2" % "3.1.1.0",
or any other version that works for you from scalatestplus-mockito. If you are using scalatestplus-playm please read Using MockitoSugar of scalatestplus-play deprecated.

Disable singleton when testing with ScalaTest in Play for Scala

I have the following #Singleton in my Play for Scala application that loads on startup:
#Singleton
class Scheduler #Inject()(#Named("mainEtl") mainEtl: ActorRef, system: ActorSystem) {
// some code
}
This is the module where Scheduler is declared. The module is enabled in application.conf:
class Module extends AbstractModule {
def configure() = {
bind(classOf[Scheduler]).asEagerSingleton
}
}
And the related module definition to configure the #Named injected object, also declared in application.conf:
class AkkaBindings extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[MainEtl]("mainEtl")
}
}
When I run any ScalaTest test, apparently the singleton starts running because I get an error saying that it doesn't find MainEtl (the object injected in the Scheduler class). The point is that I don't need to run the singleton for my tests, so I need to disable it.
This is how I invoke the Play application in my tests:
class ManageBanksTest extends PlaySpec with OneAppPerSuite with MockitoSugar {
implicit override lazy val app = new GuiceApplicationBuilder().build
// more test code
}
This is how I tried to disable it, but it doesn't work as I get the same error:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Scheduler]
.build
Alternatively, I could mock Scheduler, but I would have to mock also the #Named injected object and I couldn't find information on how to achieve that.
Any ideas?
This is the solution: to disable the Module class not to declare Scheduler as singleton:
implicit override lazy val app = new GuiceApplicationBuilder()
.disable[Module]
.build
import com.google.inject.AbstractModule
import com.google.inject.name.Names
import org.specs2.mock.Mockito
import play.api.inject.guice.{GuiceApplicationBuilder, GuiceableModule}
val modules = Option(new AbstractModule {
override def configure() = {
val mockMainETL = mock[MainEtl]
bind(classOf[ActorRef])
.annotatedWith(Names.named("mainEtl"))
.toInstance(mockMainETL)
val mock1 = mock[ManageBanksDAO]
mock1.readMany answers { _ => Future{seqMany}}
val mockManageBanks = mock[ManageBanks]
bind(classOf[ManageBanks]).toInstance(new ManageBanks(mock1))
}
})
lazy val app = new GuiceApplicationBuilder()
.overrides(modules.map(GuiceableModule.guiceable).toSeq: _*)
.build
Try configuring your mock inside modules and add those modules while initializing your application. This will inject custom mocks.
Also instead of this :
val controller = new ManageBanks(mock1)
Try this:
val controller = app.injector.instanceOf(classOf[ManageBanks])

MockServer in org.specs2 tests

I use playframework 2.2.6 scala.
I want to write integration tests for my application. But my application requests some service by http and I want to mock it with mockServer. But I don't know when to start and stop mockServer cause tests use futures
#RunWith(classOf[JUnitRunner])
class AppTest extends Specification with Around {
def around[T](t: => T)(implicit e: AsResult[T]): Result = {
val port = 9001
val server = new MockServer()
server.start(port, null)
val mockServerClient = new MockServerClient("127.0.0.1", port)
// mockServerClient rules
val result = AsResult.effectively(t)
server.stop()
result
}
"Some test" should {
"some case" in new WithApplication {
val request: Future[SimpleResult] = route(...).get
status(request) must equalTo(OK)
contentAsString(request) must contain(...)
}
"some other case" in new WithApplication {
//
}
}
}
With this code I have java.net.ConnectException: Connection refused: /127.0.0.1:9001. And I can't do this without server.stop cause that server must be run in different tests.
I found solution, I looked source code of WithApplication (it extends Around) and wrote abstract class WithMockServer:
abstract class WithMockServer extends WithApplication {
override def around[T: AsResult](t: => T): Result = {
Helpers.running(app) {
val port = Play.application.configuration.getInt("service.port").getOrElse(9001)
val server = new MockServer(port)
val mockServerClient = new MockServerClient("127.0.0.1", port)
// mockServer rules
val result = AsResult.effectively(t)
server.stop()
result
}
}
}
And in each test cases I replaced in new WithApplication with in new WithMockServer

Scala: how can I perform actions when test are over?

I'm using scalatest_2.11 version 2.2.1. I'm trying to write test that run on a SparkContext. How can I initiate a SparkContext when the tests begin, take this Sc thorugh all the tests and then stop it when they are all done?
(I know that it suppose to stop by itself, but I'sd still like to do it myself)
You can use BeforeAndAfterAll from ScalaTest. Define a base trait that starts and stops the SparkContext and use it with your other tests.
trait SparkTest extends BeforeAndAfterAll {
self: Suite =>
#transient var sc: SparkContext = _
override def beforeAll {
val conf = new SparkConf().
setMaster("local[*]").
setAppName("test")
sc = new SparkContext(conf)
super.beforeAll()
}
override def afterAll: Unit = {
try {
sc.stop()
} finally {
super.afterAll
}
}
}
// Mix-in the trait with your tests like below.
class MyTest extends FunSuite with SparkTest {
test("my test") {
// you can access "sc" here.
}
}

Scala simple funsuite unit test with akka actors fails

Hey i want to build some small Funsuite test for akka actor application but after combining Testkit with FunSuiteLike i cant call th test anymore.
Somebody an idea why this is happening? is Testkit and funsuite not compatible?
import org.scalatest.{FunSuiteLike, BeforeAndAfterAll}
import akka.testkit.{ImplicitSender, TestKit, TestActorRef}
import akka.actor.{ActorSystem}
class ActorSynchroTest(_system: ActorSystem) extends TestKit(_system) with FunSuiteLike with BeforeAndAfterAll with ImplicitSender{
val actorRef = TestActorRef(new EbTreeDatabase[Int])
val actor = actorRef.underlyingActor
//override def afterAll = TestKit.shutdownActorSystem( system )
test("EbTreeDatabase InsertNewObject is invoked"){
val idList = List(1024L,1025L,1026L,1032L,1033L,1045L,1312L,1800L)
idList.
foreach(x => actorRef ! EbTreeDataObject[Int](x,x,1,None,null))
var cursor:Long = actor.uIdTree.firstKey()
var actorItems:List[Long] = List(cursor)
while(cursor!=actor.uIdTree.lastKey()){
cursor = actor.uIdTree.next(cursor)
cursor :: actorItems
}
assert(idList.diff(actorItems) == List())
}
}
The intelliJ idea test enviroment says:
One or more requested classes are not Suites: model.ActorSynchroTest
class ActorSynchroTest extends TestKit(ActorSystem("ActorSynchroTest",ConfigFactory.parseString(ActorSynchroTest.config)))
with DefaultTimeout with ImplicitSender
with FunSuiteLike with Matchers with BeforeAndAfterAll {
...
}
object ActorSynchroTest {
// Define your test specific configuration here
val config = """
akka {
loglevel = "WARNING"
}
"""
}
Different initialization of the testkit worked in the end before the standard config was used which didn't fit