UmNyobe
UmNyobe

Reputation: 22910

Test if a function is called in a given scope in scala

I'm following the scala course in coursera and I was asked to implement set operations in the last exercise. One of the test I failed was called

exists should be implemented in terms of forall

Both exists and forall signatures are :

type Set = Int => Boolean

def forall(s: Set, p: Int => Boolean): Boolean = {}
def exists(s: Set, p: Int => Boolean): Boolean = {

   /*should eventually call forall */
}

I am not asking for the implementation, but how to perform such a unit test in scala

Upvotes: 3

Views: 3500

Answers (2)

Vladimir Matveev
Vladimir Matveev

Reputation: 127941

This is fairly easy done with mock objects. I'm using Mockito in my Java projects, and it is pretty usable from Scala too, especially together with Scalatest.

Put this code to project_dir/build.sbt:

scalaVersion := "2.10.2"

libraryDependencies ++= Seq(
  "org.scalatest" %% "scalatest" % "2.0.M8",
  "org.mockito" % "mockito-core" % "1.9.5"
)

Then put this code to project_dir/src/main/test/test.scala:

import org.scalatest.{FlatSpec,ShouldMatchers}
import org.scalatest.mock.MockitoSugar

package object test {
  type Set = Int => Boolean
}

package test {
  class Foraller {
    def forall(s: Set, p: Int => Boolean): Boolean = ???
  }

  class Exister(foraller: Foraller) {
    def exists(s: Set, p: Int => Boolean): Boolean = ???  // Fails
    // def exists(s: Set, p: Int => Boolean): Boolean = foraller.forall(s, p)  // Passes
  }

  class Test extends FlatSpec with ShouldMatchers with MockitoSugar {
    "Exister" should "use Foraller in its exists method" in {

      val foraller = mock[Foraller]

      val exister = new Exister(foraller)

      val set: Set = _ == 1
      val pred: Int => Boolean = _ > 0

      exister.exists(set, pred)

      import org.mockito.Mockito._

      verify(foraller).forall(set, pred)
    }
  }
}

Then invoke sbt test command in project_dir. You should see that the test has failed. Switch comments on lines in Exister class and try again.

Here we create mock object for the class which provides forall method and we use this object inside a class which provides exists method. Mockito allows verifying whether some method on some mock object is called, and this is what is working here.

Upvotes: 2

Matthew Farwell
Matthew Farwell

Reputation: 61705

There are three methods that I can think of to start with:

1) Mock forall to throw a particular exception, and then call exists, and see if it throws that exception.

2) Instrument the code and call exists, and test afterwards to see if forall was called

3) Use a scala macro, which analyses the AST for exists and checks recursively to see if it calls forall.

Upvotes: 3

Related Questions