You can use any Java mocking framework with ScalaTest, or ScalaMock, a Scala mocking alternative. ScalaTest provides just enough syntax sugar for the three most popular Java mocking frameworks—JMock, EasyMock, and Mockito—to remove boilerplate and clarify the client code. But other than this minor syntax sugar, the libraries are used from Scala as they are in Java. This enables people familiar with a particular framework to get going quickly and enhances readability for combined Java/Scala projects using a common mocking framework. ScalaMock, the native Scala mocking framework, has been designed to integrate easily into ScalaTest suites.
Here are links to the mocking frameworks that can be used with ScalaTest:
ScalaMock is a native, open-source Scala mocking framework written by Paul Butcher that allows you to mock objects and functions. ScalaMock supports three different mocking styles:
To use ScalaMock, mix org.scalamock.scalatest.MockFactory
into your Suite
class,
as in:
import org.scalatest.flatspec.AnyFlatSpec import org.scalamock.scalatest.MockFactory class ExampleSpec extends AnyFlatSpec with MockFactory with ...
Function mocks are created with mockFunction
. The following, for example, creates a mock
function taking a single Int
argument and returning a String
:
val m = mockFunction[Int, String]
You can then set expectations set on the mock function. For example, here's how you'd state that you
expect your mock to be called once with the argument 42
, and that when called like that
it should return the string "Forty two"
:
m expects (42) returning "Forty two" once
Proxy mocks can only be used to mock Scala traits and Java interfaces. (To mock classes, singleton/companion
objects etc., please use generated mocks.)
To use proxy mocks, mix org.scalamock.ProxyMockFactory
into your test suite.
Proxy mocks are created with mock
. The following, for example, creates a mock that implements
all the Turtle
trait (interface):
val m = mock[Turtle]
You can then set expectations on each of the methods within those traits. Here's an example:
m expects 'setPosition withArgs (10.0, 10.0) m expects 'forward withArgs (5.0) m expects 'getPosition returning (15.0, 10.0)
By default, an expectation accepts any arguments and a single call. The following two statements are equivalent:
m expects 'forward withArgs (*) once m expects 'forward
As a convenience, proxy mocks also support the stubs
method. The following two statements are equivalent:
m expects 'forward anyNumberOfTimes m stubs 'forward
Generated mocks rely on the ScalaMock compiler plugin.
Classes that are going to be mocked need to be declared with the org.scalamock.annotation.mock
annotation. To mock a class together with its companion object, use
org.scalamock.annotation.mockWithCompanion
. To mock a standalone singleton object, use
org.scalamock.annotation.mockObject
.
In addition to MockFactory
, your test class also needs to mix in GeneratedMockFactory
.
Then, to create a regular mock object, use mock
:
val m = mock[Turtle] m.expects.forward(10.0) twice
To mock a singleton or companion object, use mockObject
:
val m = mockObject(Turtle) m.expects.createTurtle
And to mock a constructor invocation, use newInstance
:
val m = mock[Turtle] m.expects.newInstance('blue) m.expects.forward(10.0)
You can specify expectations about the arguments with which a function or method is called and how many times it will be called. In addition, you can instruct a mock to return a particular value or throw an exception when that expectation is met.
To specify expected arguments for a functional mock, use expects
. To specify expected
arguments for a proxy mock, use withArgs
or withArguments
.
If no expected arguments are given, mocks accept any arguments.
To specify arguments that should simply be tested for equality, provide the expected arguments as a tuple:
m expects ("this", "that")
ScalaMock currently supports two types of generalized matching: wildcards and epsilon matching.
Wildcard values are specified with an *
(asterisk). For example:
m expects ("this", *)
will match any of the following:
m("this", 42) m("this", 1.0) m("this", null)
Epsilon matching is useful when dealing with floating point values. An epsilon match is
specified with the ~
(tilde) operator:
m expects (~42.0)
will match:
m(42.0) m(42.0001) m(41.9999)
but will not match:
m(43.0) m(42.1)
If you're using generated mocks, you need do nothing special to set expectations on methods
that take repeated parameters. If you're using proxy mocks you will need to use
the **
operator. For example, given:
def takesRepeatedParameter(x: Int, ys: String*)
you can set an expectation with:
m expects 'takesRepeatedParameter withArgs(42, **("red", "green", "blue"))
More complicated argument matching can be implemented by using where
to pass a predicate:
m = mockFunction[Double, Double, Unit] m expects { where _ < _ }
m = mock[Turtle] m expects 'setPosition where { (x: Double, y: Double) => x < y }
You can instruct a mock to return a specific value with returns
or returning
:
m1 returns 42 m2 expects ("this", "that") returning "the other"
If no return value is specified, functional mocks return null.asInstanceOf[R]
, where R
is the
return type (which equates to 0
for Int
, 0.0
for Double
etc.).
If no return value is specified, proxy mocks return null
. This works correctly for most return
types, but not for methods returning primitive types (Int
, Double
etc.), where returning
null
leads to a NullPointerException
. So you will need to explicitly specify a return value
for such methods. (This restriction may be lifted in the future.)
You can return a computed value (or throw a computed exception) with onCall
, for example:
val mockIncrement = mockFunction[Int, Int] m expects (*) onCall { x: Int => x + 1 }
Instead of a return value, a mock can be instructed to throw:
m expects ("this", "that") throws new RuntimeException("what's that?")
By default, mocks expect one or more calls (i.e., only fail if the function or method is never
called). An exact number of calls or a range can be set with repeat
:
m1 returns 42 repeat 3 to 7 m2 expects (3) repeat 10
There are various aliases for common expectations and styles:
m1 expects ("this", "that") once m2 returns "foo" noMoreThanTwice m3 expects (42) repeated 3 times
For a full list, see org.scalamock.Expectation
.
By default, expectations can be satisfied in any order. For example:
m expects (1) m expects (2) m(2) m(1)
A specific sequence can be enforced with inSequence
:
inSequence { m expects (1) m expects (2) } m(2) // throws ExpectationException m(1)
Multiple sequences can be specified. As long as the calls within each sequence happen in the correct order, calls within different sequences can be interleaved. For example:
val m1 = mock[Turtle] val m2 = mock[Turtle] inSequence { m1.expects.setPosition(0.0, 0.0) m1.expects.penDown m1.expects.forward(10.0) m1.expects.penUp } inSequence { m2.expects.setPosition(1.0, 1.0) m2.expects.turn(90.0) m2.expects.forward(1.0) m2.expects.getPosition returning (2.0, 1.0) } m2.setPosition(1.0, 1.0) m1.setPosition( 0.0, 0.0) m1.penDown m2.turn(90.0) m1.forward(10.0) m2.forward(1.0) m1.penUp expect((2.0, 1.0)) { m2.getPosition }
To specify that there is no constraint on ordering, use inAnyOrder
(there is an implicit
inAnyOrder
at the top level). Calls to inSequence
and inAnyOrder
can be arbitrarily
nested. For example:
m.expects.a inSequence { m.expects.b inAnyOrder { m.expects.c inSequence { m.expects.d m.expects.e } m.expects.f } m.expects.g }
If faced with a difficult to debug failing expectation, consider mixing
one or both of the org.scalamock.VerboseErrors
or org.scalamock.CallLogging
traits
into your test suite:
class ExampleSpec extends AnyFlatSpec with MockFactory with VerboseErrors with CallLogging ...
Next, learn about property-based testing.
ScalaTest is brought to you by Bill Venners and Artima.
ScalaTest is free, open-source software
released under the Apache
2.0 license.
If your company loves ScalaTest, please consider sponsoring the project.
Copyright © 2009-2025 Artima, Inc. All Rights Reserved.