Search code examples
scalamockitowildcardscalatest

How to use conditional mock in Mockito


I have a scala method call mocked in with mockito.

Let the object be a and method be b and the method b takes parameter of type Map[String, String]. I want to have a Map which meets a certain condition. I dont know all the key value pairs of this Map but I want to ensure that the Map has key value pairs like key1 -> value1 and key2 -> value2 when I use something like this

when(a.b(any[Map[String, String]])) thenReturn something

Here any is a static member in org.mockito. But I cant use this in here as this mock is satisfied for Map with any key and value. How to achieve a conditional mock in this case ??

I am looking for a utility which is analogous to where method which is in org.scalamock.matchers.Matchers


Solution

  • Try answers from IdiomaticMockito like so

    import org.scalatest._
    import org.mockito.{ArgumentMatchersSugar, IdiomaticMockito}
    
    trait Foo {
      def bar(m: Map[String, String]): String
    }
    
    class FooSpec extends FlatSpec with Matchers with IdiomaticMockito with ArgumentMatchersSugar {
      "Foo object" should "say woohoo" in {
        val foo = mock[Foo]
        foo.bar(*) answers ((m: Map[String, String]) => if (m.exists(_ == ("key1", "value1"))) "woohoo" else "boom")
        foo.bar(Map("key1" -> "value1")) should be ("woohoo")
      }
    }
    

    Here we pass a conditional response to answers like so

    if (m.exists(_ == ("key1", "value1"))) "woohoo" else "boom")
    

    Note we use mockito-scala which is vanilla Mockito in addition to being aware of Scala specifics:

    libraryDependencies += "org.mockito" %% "mockito-scala" % "1.5.11"
    

    Here is the same solution with vanilla Mockito

    import org.scalatest._
    import org.mockito.Mockito
    import org.mockito.Mockito._
    import org.mockito.ArgumentMatchers._
    
    trait Foo {
      def bar(m: Map[String, String]): String
    }
    
    class FooSpec extends FlatSpec with Matchers {
      "Foo object" should "say woohoo old syntax" in {
        val foo = Mockito.mock(classOf[Foo])
        doAnswer({ args =>
          val m = args.getArgument[Map[String, String]](0)
          if (m.exists(_ == ("key1", "value1"))) "woohoo" else "boom"
        }).when(foo).bar(any[Map[String, String]])
    
        foo.bar(Map("key1" -> "value1")) should be ("woohoo")
      }
    }