Nikolay
Nikolay

Reputation: 53

Scala test traits with Mockito

I'm new one in Scala. Currently I'm traing to implement a mock test for traits. Can somebody help me with implementation? I want to mock the methods seasonalityDao.doSomeForB and seasonalityDao.doSomeForB1 inside of the trait SeasonalityServiceImpl and test method hMock.doSomeForF().

Update: I have corrected the code according comments below. In this case, when I try to veryfy mocked methods verify(sMock).doSomeForB() verify(sMock).doSomeForB1(), I receive next error: Wanted but not invoked: seasonalityDao.doSomeForB(); -> at Main$$anonfun$1.apply$mcV$sp(Main.scala:12) Actually, there were zero interactions with this mock.

Here is a code(I have just simplified significant part of project for an example):

import org.scalatest._
import org.mockito.Mockito._

class Main extends FunSuite with SeasonalityServiceComponentImpl with SeasonalityDaoComponent {
  test("some test") {
    def hMock = mock(classOf[SeasonalityServiceImpl])
    def sMock = mock(classOf[SeasonalityDao])

    when(sMock.doSomeForB()).thenReturn(Option(2))
    when(sMock.doSomeForB1()).thenReturn(10)

    verify(sMock).doSomeForB()
    verify(sMock).doSomeForB1()

    println("With Option " + hMock.doSomeForF())
    println("Without Option " + hMock.doSomeForF1())
  }

  override def seasonalityDao: SeasonalityDao = mock(classOf[SeasonalityDao])

  override def seasonalityService: SeasonalityService = mock(classOf[SeasonalityService])
}

trait SeasonalityDaoComponent {
  def seasonalityDao: SeasonalityDao

  trait SeasonalityDao {
    def doSomeForB(): Option[Int]
    def doSomeForB1(): Int
  }
}

trait SeasonalityServiceComponent {
  def seasonalityService: SeasonalityService

  trait SeasonalityService {
    def doSomeForF(): Option[Int]
    def doSomeForF1(): Int
  }
}

trait SeasonalityServiceComponentImpl extends SeasonalityServiceComponent {
  this: SeasonalityDaoComponent =>

  trait SeasonalityServiceImpl extends SeasonalityService {
    def doSomeForF(): Option[Int] = {
      seasonalityDao.doSomeForB()
    }
    def doSomeForF1(): Int = {
      seasonalityDao.doSomeForB1()
    }
  }
}

Upvotes: 0

Views: 2940

Answers (1)

Iulian Dragos
Iulian Dragos

Reputation: 5712

If I understand correctly, you expect to have calls on your mock for doSomeForB and doSomeForB1. But your code verifies this expectation before you call them, so the test fails.

Moreover, your mocks are defined as local methods, meaning on each invocation you get a new mock object. You need to turn them into local vals, so you interact (and verify) the same instance.

Modify it to look like:

  test("some test") {
   // this seems unused -->>  def hMock = mock(classOf[SeasonalityServiceImpl])
    val sMock = mock(classOf[SeasonalityDao]) // you need it to be a val, not a def

    when(sMock.doSomeForB()).thenReturn(Option(2))
    when(sMock.doSomeForB1()).thenReturn(10)

    println("With Option " + sMock.doSomeForF()) // note that you should call them on sMock
    println("Without Option " + sMock.doSomeForF1())

    verify(sMock).doSomeForB()
    verify(sMock).doSomeForB1()
  }

Upvotes: 2

Related Questions