12

I am really new to Scala. I tried to mock a simple Scala function using Mockito, but I get the following error. I have checked the internet but I was unable to find out the error.

object TempScalaService {
  def login(userName: String, password: String): Boolean = {
    if (userName.equals("root") && password.equals("admin123")) {
      return true
    }
    else return false
  }
}

And my test class is below

class TempScalaServiceTest extends FunSuite with MockitoSugar{

  test ("test login "){
    val service = mock[TempScalaService.type]
    when(service.login("user", "testuser")).thenReturn(true)
    //some implementation
  }
}

But I get the following error:

Cannot mock/spy class     com.pearson.tellurium.analytics.aggregation.TempScalaService$
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class    com.pearson.tellurium.analytics.aggregation.TempScalaService$
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
   at  org.scalatest.mock.MockitoSugar$class.mock(MockitoSugar.scala:74)
    at    com.pearson.tellurium.analytics.aggregation.TempScalaServiceTest.mock(Temp    ScalaServiceTest.scala:7)
at     com.pearson.tellurium.analytics.aggregation.TempScalaServiceTest$$anonfun$    1.apply$mcV$sp(TempScalaServiceTest.scala:10)
    at    com.pearson.tellurium.analytics.aggregation.TempScalaServiceTest$$anonfun$    1.apply(TempScalaServiceTest.scala:9)
    at     com.pearson.tellurium.analytics.aggregation.TempScalaServiceTest$$anonfun$    1.apply(TempScalaServiceTest.scala:9)
    at    org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:    22)
    at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
Dilan
  • 1,389
  • 5
  • 14
  • 24
  • You don't need to use `.equals()` for Strings in Scala. Try it: `"hi" == new String("hi")` is true. Also, `if (condition) { return true } else return false` can be shortened to just `return condition` or even `condition`. – Brian McCutchon Sep 13 '17 at 05:15

3 Answers3

18

You can define the method in a trait which your object extends. Then simply mock the trait:

trait Login {
  def login(userName: String, password: String): Boolean
}

object TempScalaService extends Login {
   def login(userName: String, password: String): Boolean = {
     if (userName.equals("root") && password.equals("admin123")) {
   return true
   }
    else return false
  }
}

//in your test
val service = mock[Login]
Dan Simon
  • 12,891
  • 3
  • 49
  • 55
  • 1
    This soln works for op question but I have noticed in this approach it doesn't allow you to mock `login` call. ie you can't use `when(mockService.login(any, any)).thenReturn(false)` because when you call `service.login` on mocked service it still internally calls actual login. so you need to provide actual `userName` and `password`. – nir Feb 11 '22 at 18:22
10

You cannot mock objects, try to move your code to a class:

class TempScalaService() {
  def login(userName: String, password: String): Boolean = {
    if (userName.equals("root") && password.equals("admin123")) {
      return true
    }
    else return false
  }
}

and create a service:

object TempScalaService {
   private val service = TempScalaService()

   def apply() = service
}

This would be better with a dependency injection framework, but it will work for now.

Now, for the test, use:

val service = mock[TempScalaService]
when(service.login("user", "testuser")).thenReturn(true)
Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
LuisKarlos
  • 527
  • 6
  • 6
-4

You can create a Scala Companion Object:

  1. Write test cases for you class.
  2. Let that object do the external world interaction.
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83