Archive for June, 2012

ScalaMock 3.0-M1

ScalaMock 3.0-M1 (scaladoc) for Scala 2.10.0-M4 is now released. It supports:

  • Mock functions, traits and classes
  • Both expectation-first and record-then-verify (Mockito-style) mocking
  • ScalaTest and Specs2

To use with sbt:

libraryDependencies +=
  "org.scalamock" %% "scalamock-scalatest-support" % "3.0-M1"

For background information, see ScalaMock 3.0 Preview Release.

It’s been tested against overloaded, curried and polymorphic methods, by-name parameters, path-dependent types and type projections. There may still be corner cases that aren’t handled correctly, please report a bug if you find one.

ScalaMock 3.0 Preview Release

Update: ScalaMock 3.0-M4 for Scala 2.10.0-RC1 is now released.

The current version of ScalaMock makes use of a compiler plugin to generate typesafe mock objects. This works, but has a number of problems, not least of which is the complicated nature of the build system required (meaning that it currently only works with sbt). The recent preview release of Scala 2.10 has opened up a new approach via its support for macros.

I’ve just released a preview of ScalaMock 3.0, a “from the ground up” rewrite using macros. It’s not yet as capable as ScalaMock 2.x (it can only mock traits – there’s no support for mocking classes, singleton/companion objects or object creation yet) but it’s certainly complete enough to be useful, I hope.

One significant (and frequently requested!) enhancement over ScalaMock 2.x is support for Mockito-style “record then verify” mocking as well as the more traditional “setup expectations” style.

The source is available on GitHub, and a snapshot release (Scala 2.10.0-M3 only) is available on Sonatype:

libraryDependencies +=
  "org.scalamock" %% "scalamock-scalatest-support" % "3.0-SNAPSHOT"

You can see examples of it in use in GitHub.

Here’s an example of a test written using the “setup expectations” style:

class ControllerTest extends FunSuite with MockFactory {

  test("draw line") {
    val mockTurtle = mock[Turtle]
    val controller = new Controller(mockTurtle)

    inSequence {
      inAnyOrder {
        (mockTurtle.penUp _) expects ()
        (mockTurtle.getPosition _) expects () returning (0.0, 0.0)
        (mockTurtle.getAngle _) expects () returning 0.0
      }
      (mockTurtle.turn _) expects ~(Pi / 4)
      (mockTurtle.forward _) expects ~sqrt(2.0)
      (mockTurtle.getAngle _) expects () returning Pi / 4
      (mockTurtle.turn _) expects ~(-Pi / 4)
      (mockTurtle.penDown _) expects ()
      (mockTurtle.forward _) expects 1.0
    }

    controller.drawLine((1.0, 1.0), (2.0, 1.0))
  }
}

and here’s the same example rewritten to use the Mockito-style record and then verify approach:

class ControllerTest extends FunSuite with MockFactory {
  import scala.language.postfixOps

  test("draw line") {
    val mockTurtle = stub[Turtle]
    val controller = new Controller(mockTurtle)

    inSequence {
      inAnyOrder {
        (mockTurtle.getPosition _) when () returns (0.0, 0.0)
        (mockTurtle.getAngle _) when () returns 0.0 once
      }
      (mockTurtle.getAngle _) when () returns Pi / 4
    }

    controller.drawLine((1.0, 1.0), (2.0, 1.0))

    inSequence {
      (mockTurtle.turn _) verify ~(Pi / 4)
      (mockTurtle.forward _) verify ~sqrt(2.0)
      (mockTurtle.turn _) verify ~(-Pi / 4)
      (mockTurtle.penDown _) verify ()
      (mockTurtle.forward _) verify 1.0
    }
  }
}

Right now, it supports:

  • Mock functions (including higher-order functions)
  • Polymorphic traits
  • Polymorphic methods
  • Curried methods
  • Overloaded methods

Here’s my todo list:

  • Sort out the documentation
  • Take advantage of macro types (type providers) when available in a subsequent Scala release. This will enable a slightly nicer syntax for method mocking:

    mockObject.expects.method(arguments)

    instead of:

    (mockObject.method _) expects (arguments)

  • Mocking classes (as well as traits)
  • Mocking singleton/companion objects
  • Mocking object creation

I’d be very grateful for any feedback, in particular bug reports.