In our Scala project we use Mockito for testing purposes.
An annoying issue we have is that while using any matcher, it's always in can't resolve symbol any although it's not affect the code in builds or runtime.
There are two any implementation in Mockito (2.12):
def any[T](implicit evidence$11 : scala.reflect.ClassTag[T]) : T = { /* compiled code */ }
def any[T]() : T = { /* compiled code */ }
How can we "help" Mockito understand what any he should use?
For example:
This is a bit of self promotion but I just published a library called mockito-scala that solves this issue and many more, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.
The syntax for the matcher is improved, in particular any now solves the correct type and it drops the parentheses so it reads better
Double check your build.sbt contains
libraryDependencies += "org.mockito" % "mockito-all" % "1.10.19" % Test
and you have the following import in your test file:
import org.mockito.Matchers.any
Here is a minimal working snippet (assuming ScalaTest):
import org.scalatest.FunSuite
import org.scalatest.mockito.MockitoSugar
import org.mockito.Mockito.when
import org.mockito.Matchers.any
class CalculatorTest extends FunSuite with MockitoSugar {
test("calculator add method") {
val calcMock = mock[Calculator]
when(calcMock.add(any[Int], any[Int])).thenReturn(10)
assert(calcMock.add(7, 3) == 10)
}
}
where trait Calculator { def add(a: Int, b: Int): Int }
Related
In scalatest, you’re supposed to be able to test boolean properties using symbols like this:
iter shouldBe 'traversableAgain
But this notation have been deprecated in the most recent versions of scala, so now you’re supposed to write:
iter shouldBe Symbol("traversableAgain")
Which is a bit ugly. Is there any better alternative?
Consider BePropertyMatcher which provides type-safe predicate matching syntax
iter should be (traversableAgain)
for example
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.{BePropertyMatchResult, BePropertyMatcher}
import org.scalatest.matchers.should.Matchers
trait CustomMatchers {
val traversableAgain = new BePropertyMatcher[Iterator[_]] {
def apply(left: Iterator[_]): BePropertyMatchResult =
BePropertyMatchResult(left.isTraversableAgain, "isTraversableAgain")
}
}
class BePropertyMatcherExampleSpec extends AnyFlatSpec with Matchers with CustomMatchers {
"BePropertyMatcher" should "provide type-safe checking of predicates" in {
Iterator(42, 11) should be (traversableAgain)
}
}
There is also a related issue Replacement for using symbols as property matchers for 2.13+ #1679
How am I supposed to mock a nested Java class using scalamock, especially when said nested Java class is coming from a third party library?
Given the following sources:
src/main/java/Outer.java
/**
* Outer class that offers a Nested class inaccessible from Scala :(
*/
public class Outer {
public class Nested {
}
}
src/main/java/UseNestedJavaClassFromJava.java
public class UseNestedJavaClassFromJava {
private Outer.Nested nested;
}
src/main/scala/ImportNestedJavaClass.scala
// TODO uncomment the below line to break the build
//import Outer.Nested
Uncommenting the scala import line results in a compilation failure while compiling UseNestedJavaClassFromJava.java works just fine.
Full minimal example with gradle: https://github.com/billyjf/async-http-client-gradle-scala.
Apparently this was somewhat already addressed in the below question, but resorting to Java glue code or reflection trickery just for the sake of testing Scala code that leverages a Java library with nested Java classes seems a bit unreasonable to me, is there really no other solution?
Scala can't access Java inner class?
I finally found a solution using Mockito:
import org.mockito.Mockito
import org.scalamock.scalatest.MockFactory
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{FlatSpec, Matchers}
class OuterNestedTest extends FlatSpec with MockFactory with Matchers with MockitoSugar {
"Nested Java class" should "be mockable using Mockito from within a scalatest" in {
val mockedNestedJavaClass = Mockito.mock(classOf[Outer#Nested])
Mockito.when(mockedNestedJavaClass.methodWithAParam("some value"))
.thenReturn("mocked", Nil: _*)
mockedNestedJavaClass.methodWithAParam("some value") shouldBe "mocked"
}
}
class Main {
val z = new Outer;
private[this] val y:z.Inner = null
}
For more context:
Outer.Inner is interpreted as Outer$.Inner (companion object).
Official Scala website:
As opposed to Java-like languages where such inner classes are members
of the enclosing class, in Scala such inner classes are bound to the
outer object.
https://docs.scala-lang.org/tour/inner-classes.html
I am writing unit tests for an akka actor model implementation. The system contains classes and traits that need to be initialised. My issue lies with the testing of the methods. When I mock required parameters for a class, it removes the intelij compiler error, however all of the variables are set to null.
I have attempted to use
when(mock.answer).thenReturn(42)
and directly assigning the variables
val mock.answer = 42
The above two through compilation errors. "When" is not recognised and directly assigning values cases a runtime error.
Any insight would be much appreciated.
I am not sure if I understood your issue correctly, but try the self contained code snippet below and let me know if it is not clear enough:
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{FunSuite, Matchers}
import org.mockito.Mockito.when
#RunWith(classOf[JUnitRunner])
class MyTest extends FunSuite with Matchers with MockitoSugar {
trait MyMock {
def answer: Int
}
test("my mock") {
val myMock = mock[MyMock]
when(myMock.answer).thenReturn(42)
myMock.answer should be(42)
}
}
Before you point to the documentation, please point out what's wrong with this minimal, failing example:
import org.scalatest.FlatSpec
import org.scalamock.scalatest.proxy.MockFactory
class StubbingTest extends FlatSpec with MockFactory {
trait Foo {
def f(x: Int): Int
}
"foo" should "stub" in {
val foo = stub[Foo]
(foo.f _).when(3).returns(4)
assert(foo.f(3) == 4)
}
}
Which results in java.lang.NoSuchMethodException: com.sun.proxy.$Proxy4.mock$f$0() at line 11: (foo.f _).when ...
According to the documentation, this should work. What am I missing here?
I figured it out by pure luck while browsing the Scaladoc:
Change
import org.scalamock.scalatest.proxy.MockFactory
to
import org.scalamock.scalatest.MockFactory
My IDE's Auto-import failed me, but it would have really helped if the ScalaMock documentation examples included proper imports.
I am using Scalamock with ScalaTest, and am trying to mock a Java interface. I currently have:
private val _iface = mock [MyInterface]
now I want to do
_iface expects `someMethod returning "foo" once
But the compiler does not find expects.
I imported org.scalatest._ and org.scalamock.scalatest._. What else am I missing?
First of all, proxy mocks are not supported very well in ScalaMock 3, and I think they will be completely removed in ScalaMock 4. Do you really need to use proxy mocks instead macro mocks?
This should work:
package example
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import org.scalamock.scalatest.proxy.MockFactory
trait MyInterface {
def someMethod : String
}
class MyTest extends FlatSpec with Matchers with MockFactory {
"MyInterface" should "work" in {
val m = mock[MyInterface]
m.expects('someMethod)().returning("foo")
m.someMethod shouldBe "foo"
}
}
If not, please check ScalaMock proxy mocks unit tests for more examples.
I think it should be something more like:
import org.scalamock.scalatest.MockFactory
class MyTest extends FlatSpec with Matchers with MockFactory {
"MyInterface" should "work" in {
val m = mock[MyInterface]
(m.someMethod _).expects().returning("foo")
m.someMethod shouldBe "foo"
}
}
I think the expects arg is expecting the arg to the function
I use scalaMock version 4.1.0, this works for me:
For some trait:
trait MyInterface { def someMethod(n1: Int, n2: Int) }
This should be put into a test
val myInterfaceMock = mock[MyInterface]
myInterfaceMock.someMethod _ expects (1,2)
For more reading: scalaMock Guide, you'll find some examples there