Giter Club home page Giter Club logo

mockito-scala's Introduction

Mockito Scala

Mockito

The most popular mocking framework for Java, now in Scala!!!

Maven Central

Gitter chat

Cats Friendly

Why separate project?

The library has independent developers, release cycle and versioning from core mockito library (https://github.com/mockito/mockito). This is intentional because core Mockito developers don't use Scala and cannot confidently review PRs, and set the vision for the Scala library.

Dependency

  • Artifact identifier: "org.mockito:mockito-scala_[scala-version]:[version]"
  • Artifact identifier: "org.mockito:mockito-scala-scalatest_[scala-version]:[version]"
  • Artifact identifier: "org.mockito:mockito-scala-specs2_[scala-version]:[version]"
  • Artifact identifier: "org.mockito:mockito-scala-cats_[scala-version]:[version]"
  • Artifact identifier: "org.mockito:mockito-scala-scalaz_[scala-version]:[version]"
  • Latest version - see release notes
  • Repositories: Maven Central

Please ensure you don't declare mockito-core as a dependency. mockito-scala will pull the appropriate version automatically

Note: For more examples and use cases than the ones shown below, please refer to the library's specific tests

Partial unification

If you're in Scala 2.11 or 2.12 you'll probably want to add the compiler flag -Ypartial-unification, if you don't you risk some compile errors when trying to stub complex types using the idiomatic syntax

Notes for 1.13.6

We slightly changed the way one would expect no/no more interactions with a mock object in Expectations DSL. From now on, expect (...) to should only be used on stubbed methods, and can't express expectations about interactions with the mock objects itself.

In order to express expectations on a mock, one would use expect (...) on (note the use of on vs to) where such expectations are supported.

  • Instead of expect no calls to aMock, use expect no calls on aMock.
  • Instead of expect noMore calls to aMock, use expect noMore calls on aMock.

Expectations about no method calls stay the same: expect no calls to aMock.bar(*).

Notes for 1.13.0

We added a new experimental Expectations DSL for idiomatic syntax. It behaves differently from the original idiomatic verifications: the user declares intent to verify by using expect at the beginning of the line rather than at the end of it - similar to "verify" in Mockito Java.

Now, you can do expect a call to aMock.bar(*) where previously you did aMock.bar(*) was called. More examples in Expect DSL

Note that since this DSL is currently experimental, it's not stable - the DSL itself may evolve, components and base traits may move or be renamed, and incompatible changes may be introduced between minor/patch versions.

In order to use it...

  • with Scalatest base traits, mix in org.mockito.scalatest.IdiomaticMockitoBase with org.mockito.PrefixExpectations instead of org.mockito.scalatest.IdiomaticMockito (or org.mockito.scalatest.AsyncIdiomaticMockitoBase)
  • with another test framework, mix in trait org.mockito.IdiomaticMockito.WithExpect or use its companion object

Notes for v1.4.0

As Specs2 support was added, now the library has been split in 3 different artifacts

  • mockito-scala being the core
  • mockito-scala-scalatest having specific classes that provide extra support for Scalatest
  • mockito-scala-specs2 having specific classes that provide extra support for Specs2

From now on, when using the idiomatic syntax, you'll get any non-matcher parameter automatically wrapped in an eqTo, this means you shouldn't need to use it manually anymore. This is to provide a consistent behaviour when a custom scalactic.Equality has been defined for a type.

The traits that provide the specifics for each test framework are

  • Scalatest:
    • org.mockito.scalatest.MockitoSugar and org.mockito.scalatest.IdiomaticMockito for standard specs
    • org.mockito.scalatest.AsyncMockitoSugar, org.mockito.scalatest.AsyncIdiomaticMockito for async specs
  • Specs2: org.mockito.specs2.Mockito

This version also includes a lot of under-the-hood fixes and improvements that provide an even better experience.

Note for v1.2.0

As now the varargs support works consistently across the whole lib, no no special syntax is needed, so if you were using eqTo with varargs, i.e.

verify(myObj).myMethod(eqTo("arg1", "arg2"))

You must change it now to

verify(myObj).myMethod(eqTo("arg1"), eqTo("arg2"))

Migration Notes for version 1.0.0

  • DefaultAnswer was moved from org.mockito.DefaultAnswer to org.mockito.stubbing.DefaultAnswer
  • The recommended way to use the pre-defined DefaultAnswers is via the object org.mockito.DefaultAnswers
  • * matcher is now defined in org.mockito.ArgumentMatchersSugar, mixin (or use the companion object) this trait whenever you wanna use it
  • argumentCaptor[String] was removed, replace by ArgCaptor[T] (Captor[T] was renamed to ArgCaptor[T] to add clarity), ValCaptor[T] was deprecated, (see Improved ArgumentCaptor)
  • The usage of org.mockito.Answer[T] was removed from the API in favour of Function Answers
  • If you were using something like doAnswer(_ => <something>).when ... to lazily compute a return value when the method is actually called you should now write it like doAnswer(<something>).when ..., no need of passing a function as that argument is by-name
  • If you have chained return values like when(myMock.foo) thenReturn "a" thenReturn "b" etc... the syntax has changed a bit to when(myMock.foo) thenReturn "a" andThen "b" etc...
  • Idiomatic syntax has some changes to remove postFix operations and also allow support for mixing values and argument matchers Mix-and-Match
aMock.bar shouldCallRealMethod                              => aMock.bar shouldCall realMethod

aMock wasCalled on bar                                      => aMock.bar was called
aMock wasCalled onlyOn bar                                  => aMock.bar wasCalled onlyHere
aMock was never called on bar                               => aMock.bar wasNever called
aMock wasCalled twiceOn bar                                 => aMock.bar wasCalled twice
aMock wasCalled sixTimesOn bar                              => aMock.bar wasCalled sixTimes
aMock was never called                                      => aMock.bar wasNever called
aMock was never called again                                => aMock.bar wasNever calledAgain

"mocked!" willBe returned by aMock bar                      => "mocked!" willBe returned by aMock.bar
"mocked!" willBe answered by aMock bar                      => "mocked!" willBe answered by aMock.bar
((i: Int) => i * 10) willBe answered by aMock bar *         => ((i: Int) => i * 10) willBe answered by aMock.bar(*)
theRealMethod willBe called by aMock bar                    => theRealMethod willBe called by aMock.bar
new IllegalArgumentException willBe thrown by aMock bar     => new IllegalArgumentException willBe thrown by aMock.bar
  • eqToVal matcher syntax was improved to look more natural Value Class Matchers NOTE: eqToVal has been deprecated in v 1.0.2 as eqTo is now aware of value classes
verify(myObj).myMethod(eqToVal[MyValueClass](456))    => verify(myObj).myMethod(eqToVal(MyValueClass(456)))
myObj.myMethod(eqToVal[MyValueClass](456)) was called => myObj.myMethod(eqToVal(MyValueClass(456))) was called

Getting started

org.mockito.MockitoSugar

For a more detailed explanation read this

This trait wraps the API available on org.mockito.Mockito from the Java version, but it provides a more Scala-like syntax, mainly

  • Fixes the compiler errors that sometimes occurred when using overloaded methods that use varargs like doReturn
  • Eliminates the need to use classOf[T]
  • Eliminates parenthesis when possible to make the test code more readable
  • Adds spyLambda[T] to allow spying lambdas (they don't work with the standard spy as they are created as final classes by the compiler)
  • Supports mocking inline mixins like mock[MyClass with MyTrait]
  • Full support for by-name arguments (the full support was added in 1.4.0, before it was partial).
  • Adds support for working with default arguments

The companion object also extends the trait to allow the usage of the API without mixing-in the trait in case that's desired

org.mockito.ArgumentMatchersSugar

For a more detailed explanation read this

This trait exposes all the existent org.mockito.ArgumentMatchers but again it gives them a more Scala-like syntax, mainly

  • eq was renamed to eqTo to avoid clashing with the Scala eq operator for identity equality, eq also supports value classes out of the box and relies on org.scalactic.Equality[T] (see Scalactic integration)
  • any[T] works even when the type can't be inferred, removing the need of using the likes of anyString, anyInt, etc (see Notes)
  • any[T] also supports value classes (in this case you MUST provide the type parameter)
  • isNull and isNotNull are deprecated as using nulls in Scala is clear code smell
  • Adds support for value classes via anyVal[T] and eqToVal[T]() NOTE: both had been deprecated (use any[T] or eqTo[T] instead)
  • Adds function0 to easily match for a function that returns a given value
  • Adds argMatching that takes a partial function to match, i.e. argMatching({ case Baz(_, "pepe") => })

Again, the companion object also extends the trait to allow the usage of the API without mixing-in the trait in case that's desired

Value Class Matchers

eqTo and any[T] support value classes since v1.0.2, so no special syntax is needed for them (but you MUST provide the type param for any[T] otherwise you'll get a NPE)

Improved ArgumentCaptor

For a more detailed explanation read this

A new set of classes were added to make it easier, cleaner and more elegant to work with ArgumentCaptors, they also add support to capture value classes without any annoying syntax

There is a new object org.mockito.captor.ArgCaptor[T] that exposes a nicer API

Before:

val aMock  = mock[Foo]
val captor = argumentCaptor[String]

aMock.stringArgument("it worked!")

verify(aMock).stringArgument(captor.capture())

captor.getValue shouldBe "it worked!"

Now:

val aMock  = mock[Foo]
val captor = ArgCaptor[String]

aMock.stringArgument("it worked!")

verify(aMock).stringArgument(captor)

captor hasCaptured "it worked!"

As you can see there is no need to call capture() nor getValue anymore (although they're still there if you need them as capture and value respectively)

The only scenario where you still have to call capture by hand is where the argument you want to capture is Any on the method signature, in that case the implicit conversion that automatically does the capture

implicit def asCapture[T](c: Captor[T]): T = c.capture

is not called as the compiler finds no need to convert Captor[Any] into Any, as it is already an instance of Any, given that Any is the parent of every type in Scala. Because of that, the type does not need any transformation to be passed in.

There is another constructor ValCaptor[T] that should be used to capture value classes NOTE: Since version 1.0.2 ValCaptor[T] has been deprecated as ArgCaptor[T] now support both, standard and value classes

Both ArgCaptor[T] and ValCaptor[T] return an instance of Captor[T] so the API is the same for both

org.mockito.MockitoScalaSession

Basic usage

This is a wrapper around org.mockito.MockitoSession, it's main purpose (on top of having a Scala API) is to improve the search of mis-used mocks and unexpected invocations to reduce debugging effort when something doesn't work

To use it just wrap your code with it, e.g.

MockitoScalaSession().run {
    val foo = mock[Foo]
    when(foo.bar("pepe")) thenReturn "mocked"
    foo.bar("pepe") shouldBe "mocked"
}

That's it! that block of code will execute within a session which will take care of checking the use of the framework and, if the test fails, it will try to find out if the failure could be related to a mock being used incorrectly

Spies

Spies for partial mocking of real objects

"LinkedList size" should "return 100" in {
    val spiedList = spy(new util.LinkedList[String])
    when(spiedList.size).thenReturn(100)
    assert(spiedList.size === 100)
  }

Leniency

If for some reason we want that a mock created within the scope of a session does not report failures for some or all methods we can specify leniency for it.

For the whole mock or spy to be ignored by the session, so basically a mock/spy that behaves as if the session didn't exist at all, we can make it lenient, e.g.

val aMock = mock[Foo](withSettings.lenient())
val aSpy = spy(new Bar, lenient = true)

Now, if we just want to make one or more methods to be ignored by the session checks, we can make the method call lenient, this works as any other stubbing, so what it matters what matchers you define

aMock.myMethod(*) isLenient()
//or
when(aMock.myMethod(*)).isLenient()

Strict Mode

For a more detailed explanation read this

When using Scalatest and org.mockito.scalatest.IdiomaticMockito this is the default mode, you can override the strictness to be lenient by doing val strictness: Strictness = Strictness.Lenient The implication under the hood is that every test will run inside a MockitoScalaSession, so all of them will run in Strict Stub mode.

org.mockito.scalatest.IdiomaticMockito also includes org.mockito.IdiomaticMockito and org.mockito.ArgumentMatchersSugar so you have pretty much all the mockito-scala API available in one go, i.e.

class MyTest extends WordSpec with IdiomaticMockito

IMPORTANT: A session is defined on a per-test basis, and only the mocks created within the scope of the session are handled by it, so if you have class level fields with mocks, i.e. mocks that are not created within the test, they will be ignored by the session. If you use the same mocks in all or most of the tests and want to avoid the boilerplate while still usfing the advantages of strict stubbing then declare those mocks in a setup trait.

class MySpec extends WordSpec with Mockito {
   trait Setup {
      val myMock = mock[Sth] 
      myMock.someMethod returns "something" /*stub common to **all** tests -notice that if it's not used by all of them then the session will find it as an unused stubbing on those-*/
   }

   "some feature" should {
       "test whatever i want" in new Setup {
            myMock.someOtherMethod(*) returns None /*stub specific only to this test*/
             ...test
       }

      "test something else" in new Setup {
             myMock.someOtherMethod("expected value") returns Some("result")  /*stub specific only to this test*/
             ...test
       }
   }
}

This will give you a fresh new instance of myMock for each test but at the same time you only declare the creation/common stubbing once.

org.mockito.integrations.scalatest.ResetMocksAfterEachTest | org.mockito.integrations.scalatest.ResetMocksAfterEachAsyncTest

Inspired by this StackOverflow question, mockito-scala provides these traits that helps to automatically reset any existent mock after each test is run The trait has to be mixed after org.mockito.MockitoSugar in order to work, otherwise your test will not compile The code shown in the StackOverflow question would look like this if using this mechanism

NOTE: MockitoFixture and ResetMocksAfterEachTest are mutually exclusive, so don't expect them to work together

class MyTest extends PlaySpec with MockitoSugar with ResetMocksAfterEachTest

private val foo = mock[Foo]

override def fakeApplication(): Application = new GuiceApplicationBuilder().overrides(bind[Foo].toInstance(foo)).build

The main advantage being we don't have to remember to reset each one of the mocks...

If for some reason we want to have a mock that is not reset automatically while using this trait, then it should be created via the companion object of org.mockito.MockitoSugar so is not tracked by this mechanism

Idiomatic Mockito

By adding the trait org.mockito.IdiomaticMockito you get access to some improved methods in the API

This API is heavily inspired on Scalatest's Matchers, so if you have used them, you'll find it very familiar

Here we can see the old syntax on the left and the new one on the right

trait Foo {
  def bar: String
  def bar(v: Int): Int
}
  
val aMock = mock[Foo]  
  
when(aMock.bar) thenReturn "mocked!"                            <=> aMock.bar returns "mocked!"
when(aMock.bar) thenReturn "mocked!" thenReturn "mocked again!" <=> aMock.bar returns "mocked!" andThen "mocked again!"
when(aMock.bar) thenCallRealMethod()                            <=> aMock.bar shouldCall realMethod
when(aMock.bar).thenThrow[IllegalArgumentException]             <=> aMock.bar.shouldThrow[IllegalArgumentException]
when(aMock.bar) thenThrow new IllegalArgumentException          <=> aMock.bar throws new IllegalArgumentException
when(aMock.bar) thenAnswer(_ => "mocked!")                      <=> aMock.bar answers "mocked!"
when(aMock.bar(any)) thenAnswer(_.getArgument[Int](0) * 10)     <=> aMock.bar(*) answers ((i: Int) => i * 10)

doReturn("mocked!").when(aMock).bar                             <=> "mocked!" willBe returned by aMock.bar
doAnswer(_ => "mocked!").when(aMock).bar                        <=> "mocked!" willBe answered by aMock.bar
doAnswer(_.getArgument[Int](0) * 10).when(aMock).bar(any)       <=> ((i: Int) => i * 10) willBe answered by aMock.bar(*)
doCallRealMethod.when(aMock).bar                                <=> theRealMethod willBe called by aMock.bar
doThrow(new IllegalArgumentException).when(aMock).bar           <=> new IllegalArgumentException willBe thrown by aMock.bar

doNothing().when(aMock).bar                                     <=> aMock.bar.doesNothing()
  
verifyZeroInteractions(aMock)                                   <=> aMock wasNever called
verify(aMock).bar                                               <=> aMock.bar was called
verify(aMock).bar(any)                                          <=> aMock.bar(*) was called

verify(aMock, only).bar                                         <=> aMock.bar wasCalled onlyHere
verify(aMock, never).bar                                        <=> aMock.bar wasNever called

verify(aMock, times(2)).bar                                     <=> aMock.bar wasCalled twice
verify(aMock, times(2)).bar                                     <=> aMock.bar wasCalled 2.times

verify(aMock, times(6)).bar                                     <=> aMock.bar wasCalled sixTimes
verify(aMock, times(6)).bar                                     <=> aMock.bar wasCalled 6.times

verify(aMock, atLeast(6)).bar                                   <=> aMock.bar wasCalled atLeastSixTimes
verify(aMock, atLeast(6)).bar                                   <=> aMock.bar wasCalled atLeast(sixTimes)
verify(aMock, atLeast(6)).bar                                   <=> aMock.bar wasCalled atLeast(6.times)

verify(aMock, atMost(6)).bar                                    <=> aMock.bar wasCalled atMostSixTimes
verify(aMock, atMost(6)).bar                                    <=> aMock.bar wasCalled atMost(sixTimes)
verify(aMock, atMost(6)).bar                                    <=> aMock.bar wasCalled atMost(6.times)

verify(aMock, timeout(2000).atLeast(6)).bar                     <=> aMock.bar wasCalled (atLeastSixTimes within 2.seconds)

verifyNoMoreInteractions(aMock)                                 <=> aMock wasNever calledAgain

val order = inOrder(mock1, mock2)                               <=> InOrder(mock1, mock2) { implicit order =>
order.verify(mock2).someMethod()                                <=>   mock2.someMethod() was called
order.verify(mock1).anotherMethod()                             <=>   mock1.anotherMethod() was called
                                                                <=> }

As you can see the new syntax reads a bit more natural, also notice you can use * instead of any[T]

Check the tests for more examples

NOTE: When using the willBe syntax for stubbing, you can only stub one value to be returned, this is due to a limitation of the type inference. If for some reason you have to do that (ideally all functions should be referentially transparent, so you wouldn't have to), you can use the traditional syntax via the MockitoSugar companion object MockitoSugar.doReturn("meh").when(myMock).foo or you can use an answer that can decide what to return given whatever condition you need to simulate { (args) => if(<condition>) something else somethingElse } willBe answered by myMock.foo

Expect DSL

NOTE: This DSL is experimental, may be unstable and may introduce incompatible changes between minor/patch versions

This DSL is available as a prefix alternative to aMock.bar was called DSL provided by Idiomatic Mockito while keeping the original mocking and stubbing functionality. As you can see, with the new syntax you declare the intent of verification before describing the called pattern, so it reads even more naturally then before.

It is available via org.mockito.IdiomaticMockito.WithExpect mix-in (or its companion object). Mocking and stubbing works the same as before, and below are the examples of how verifications should be done.

trait Foo {
  def bar: String
  def bar(v: Int): Int
}
  
val aMock = mock[Foo]  
  
verifyZeroInteractions(aMock)                     <=> expect no calls on aMock

verify(aMock).bar                                 <=> expect a call to aMock.bar
verify(aMock).bar(any)                            <=> expect a call to aMock.bar(*)

verify(aMock, only).bar                           <=> expect only call to aMock.bar
verify(aMock, never).bar                          <=> expect no calls to aMock.bar

verify(aMock, times(2)).bar                       <=> expect exactly 2.calls to aMock.bar
verify(aMock, times(2)).bar                       <=> expect two calls to aMock.bar
verify(aMock, times(2)).bar                       <=> expect (2.calls) to aMock.bar

verify(aMock, times(6)).bar                       <=> expect exactly 6.calls to aMock.bar
verify(aMock, times(6)).bar                       <=> expect six calls to aMock.bar
verify(aMock, times(6)).bar                       <=> expect (6.calls) to aMock.bar

verify(aMock, atLeast(6)).bar                     <=> expect atLeast 6.calls to aMock.bar
verify(aMock, atLeast(6)).bar                     <=> expect atLeastSix calls to aMock.bar

verify(aMock, atMost(6)).bar                      <=> expect atMost 6.calls to aMock.bar
verify(aMock, atMost(6)).bar                      <=> expect atMostSix calls to aMock.bar

verify(aMock, timeout(2000).times(2)).bar         <=> expect (2.calls within 2.seconds) to aMock.bar
verify(aMock, timeout(2000).atLeast(6)).bar       <=> expect (atLeast(6.calls) within 2.seconds) to aMock.bar

verifyNoMoreInteractions(aMock)                   <=> expect noMore calls on aMock
verifyNoMoreInteractions(ignoreStubs(aMock))      <=> expect noMore calls(ignoringStubs) on aMock

val order = inOrder(mock1, mock2)                 <=> InOrder(mock1, mock2) { implicit order =>
order.verify(mock2).someMethod()                  <=>   expect a call to mock2.someMethod()
order.verify(mock1).anotherMethod()               <=>   expect a call to mock1.anotherMethod()
                                                  <=> }

Default Answers

We defined a new type org.mockito.stubbing.DefaultAnswer which is used to configure the default behaviour of a mock when a non-stubbed invocation is made on it.

The object org.mockito.DefaultAnswers contains each one of the provided ones

All the mocks created will use ReturnsSmartNulls by default, this is different to the Java version, which returns null for any non-primitive or non-final class.

A "Smart Null", is nothing else than a mock of the type returned by the called method. The main advantage of doing that is that if the code tries to call any method on this mock, instead of failing with a NPE the mock will throw a different exception with a hint of the non-stubbed method that was called (including its params), this should make much easier the task of finding and fixing non-stubbed calls

Most of the Answers defined in org.mockito.Answers have it's counterpart in org.mockito.DefaultAnswers, and on top of that we also provide ReturnsEmptyValues which will try its best to return an empty object for well known types, i.e. Nil for List, None for Option etc. This DefaultAnswer is not part of the default behaviour as we think a SmartNull is better, to explain why, let's imagine we have the following code.

class UserRepository {
  def find(id: Int): Option[User]
}
class UserController(userRepository: UserRepository) {
  def get(userId: Int): Option[Json] = userRepository.find(userId).map(_.toJson)
}

class UserControllerTest extends WordSpec with IdiomaticMockito {

  "get" should {
     "return the expected json" in {
        val repo = mock[UserRepository]
        val testObj = new UserController(repo)

        testObj.get(123) shouldBe Some(Json(....)) //overly simplified for clarity
      }
    }
}

Now, in that example that test could fail in 3 different ways

  1. With the standard implementation of Mockito, the mock would return null and we would get a NullPointerException, which we all agree it's far from ideal, as it's hard to know where did it happen in non trivial code
  2. With the default/empty values, we would get a None, so the final result would be None and we will get an assertion error as None is not Some(Json(....)), but I'm not sure how much improvement over the NPE this would be, because in a non-trivial method we may have many dependencies returning Option and it could be hard to track down which one is returning None and why
  3. With a smart-null, we would return a mock[Option] and as soon as our code calls to .map() that mock would fail with an exception telling you what non-stubbed method was called and on which mock (in the example would say something you called the find method on some mock of type UserRepository)

And that's why we use option 3 as default

Of course you can override the default behaviour, for this you have 2 options

  1. If you wanna do it just for a particular mock, you can, at creation time do mock[MyType](MyDefaultAnswer)
  2. If you wanna do it for all the mocks in a test, you can define an implicit, i.e. implicit val defaultAnswer: DefaultAnswer = MyDefaultAnswer

DefaultAnswers are also composable, so for example if you wanted empty values first and then smart nulls you could do implicit val defaultAnswer: DefaultAnswer = ReturnsEmptyValues orElse ReturnsSmartNulls

Function Answers

org.mockito.Answer[T] can be a bit boilerplate-ish, mostly if you're still in Scala 2.11 (in 2.12 with SAM is much nicer), to simplify the usage for both versions is that we replaced it by standard scala functions, so instead of

when(myMock.foo("bar", 42)) thenAnswer new Answer[String] {
  override def answer(invocation: InvocationOnMock): String = i.getArgument[String](0) + i.getArgument[Int](1)
}

We can now write: (this may be nothing new for users of 2.12, but at least now the API is consistent for both 2.11 and 2.12)

when(myMock.foo("bar", 42)) thenAnswer ((i: InvocationOnMock) => i.getArgument[String](0) + i.getArgument[Int](1))

I guess we all agree that's much better, but, it gets even better, we can now pass standard functions that work over the arguments, we only need to take care to pass the right types, so the previous example would become

when(myMock.foo("bar", 42)) thenAnswer ((v1: String, v2: Int) => v1 + v2)

Mix and match

Mixing normal values with argument matchers

Since mockito 1.0.0, when you use the idiomatic syntax, you are not forced anymore to use argument matchers for all your parameters as soon as you use one, so stuff like this is now valid (not a comprehensive list, just a bunch of examples)

trait Foo {
  def bar(v: Int, v2: Int, v3: Int = 42): Int
}
  
val aMock = mock[Foo]  
  
aMock.bar(1,2) returns "mocked!"
aMock.bar(1,*) returns "mocked!"
aMock.bar(*,*) returns "mocked!"
aMock.bar(*,*, 3) returns "mocked!"

"mocked!" willBe returned by aMock.bar(1,2)
"mocked!" willBe returned by aMock.bar(1,*)
"mocked!" willBe returned by aMock.bar(*,*)
"mocked!" willBe returned by aMock.bar(*,*, 3)

aMock.bar(1,2) was called
aMock.bar(1,*) was called
aMock.bar(*,*) was called
aMock.bar(*,*, 3) was called

So far there is one caveat, if you have a curried function that has default arguments on the second (or any following) argument list, the macro that achieves this will fail, this is related to how the default method is created by the compiler. I'll write a more detailed explanation at some point, but there are more than one reason why this is probably never going to work The workaround is quite easy though, just provide a value (or a matcher) for that argument and you are good to go.

Numeric matchers

A new set of matchers to deal with number comparison were introduced (see Scalactic tolerance for approximation), the syntax is slightly different to make them more readable, so now we can write stuff like (notice the 'n')

aMock.method(5)

aMock.method(n > 4.99) was called
aMock.method(n >= 5) was called
aMock.method(n < 5.1) was called
aMock.method(n <= 5) was called

Varargs

Most matchers that makes sense to, work with varargs out of the box, the only thing to notice is that if you are passing more than one value and want to use eqTo then you should pass all of them to the same instance of eqTo e.g.

trait FooWithVarArgAndSecondParameterList {
  def bar(bells: String*)(cheese: String): String
}

foo.bar(eqTo("cow", "blue"))(*) was called //RIGHT
foo.bar(eqTo("cow"), eqTo("blue"))(*) was called //WRONG - it will complain it was expecting 2 matchers but got 3

Scalactic integration

Equality

Since version 1.0.0 the eqTo matcher uses the org.scalactic.Equality[T] typeclass, this doesn't change anything on the API and existent code will not be affected, but it allows you to override the standard equality of any class by just providing an implicit Equality in scope, e.g.

implicit val fooEquality: Equality[Foo] = new Equality[Foo] { 
  override def areEqual(a: Foo, b: Any): Boolean = /*Do the comparison as you like*/ 
}

aMock.method(eqTo(/*some foo instance/*))

Tolerance

You can use Scalactic's Spread[T] to deal with the precision errors in floating points, so you can now write stuff like

aMock.method(4.999)

aMock.method(n =~ 5.0 +- 0.001) was called

Prettifier

An instance of org.scalactic.Prettifier is implicitly pulled by the EqTo matcher to provide a nicer (and customisable) printing of your types when an verification fails. EqTo is also used internally by Mockito to print the arguments of every invocation, so you'll get a consistent printing for both the expectation and the actual call.

If you want to customise the print of any type you just need to declare your Prettifier in the implicit scope like

  implicit val prettifier: Prettifier = new Prettifier {
    override def apply(o: Any): String = o match {
      case Baz2(_, s) => s"PrettifiedBaz($s)"
      case other      => Prettifier.default(other)
    }
  }

Cats integration

By adding the module mockito-scala-cats 2 new traits are available, IdiomaticMockitoCats and MockitoCats which are meant to be mixed-in in tests that use IdiomaticMockito and MockitoSugar respectively. Please look at the tests for more detailed examples

MockitoCats

This traits adds whenF() which allows stubbing methods that return an Applicative (or an ApplicativeError) to be stubbed by just providing the content of said applicative (or the error). So for

trait Foo {
    def returnsOption[T](v: T): Option[T]
    def returnsMT[M[_], T](v: T): M[T]
}
// We can now write 
val aMock = mock[Foo]
whenF(aMock.returnsOption(*)) thenReturn "mocked!"
whenF(aMock.returnsMT[Future, String](*)) thenReturn "mocked!"
// Rather than
when(aMock.returnsOption(*)) thenReturn Some("mocked!")
when(aMock.returnsMT[Future, String](*)) thenReturn Future.successful("mocked!")

//We could also do stubbings in a single line if that's all we need from the mock
val inlineMock: Foo = whenF(mock[Foo].returnsOption(*)) thenReturn "mocked!"

// For errors we can do
type ErrorOr[A] = Either[Error, A]
val failingMock: Foo = whenF(mock[Foo].returnsMT[ErrorOr, MyClass](*)) thenFailWith Error("error")
//Rather than
val failingMock: Foo = when(mock[Foo].returnsMT[ErrorOr, MyClass](*)) thenReturn Left(Error("error"))

The trait also provides and implicit conversion from cats.Eq to scalactic.Equality so if you have an implicit cats.Eq instance in scope, it will be automatically used by the eqTo matcher.

IdiomaticMockitoCats

Similar to MockitoCats but for the idiomatic syntax (including the conversion from cats.Eq to scalactic.Equality), so the code would look like

trait Foo {
    def returnsOption[T](v: T): Option[T]
    def returnsMT[M[_], T](v: T): M[T]
}
// We can now write 
val aMock = mock[Foo]
aMock.returnsOption(*) returnsF "mocked!"
aMock.returnsMT[Future, String](*) returnsF "mocked!"
// Rather than
aMock.returnsOption(*) returns Some("mocked!")
aMock.returnsMT[Future, String](*) returns Future.successful("mocked!")

//We could also do stubbings in a single line if that's all we need from the mock
val inlineMock: Foo = mock[Foo].returnsOption(*) returnsF "mocked!"

// For errors we can do
type ErrorOr[A] = Either[Error, A]
val failingMock: Foo = mock[Foo].returnsMT[ErrorOr, MyClass](*) raises Error("error")
//Rather than
val failingMock: Foo = mock[Foo].returnsMT[ErrorOr, MyClass](*) returns Left(Error("error"))

Scalaz integration

By adding the module mockito-scala-scalaz 2 new traits are available, IdiomaticMockitoScalaz and MockitoScalaz which are meant to be mixed-in in tests that use IdiomaticMockito and MockitoSugar respectively. Please look at the tests for more detailed examples

MockitoScalaz

This traits adds whenF() which allows stubbing methods that return an Applicative (or an ApplicativeError) to be stubbed by just providing the content of said applicative (or the error). So for

trait Foo {
    def returnsOption[T](v: T): Option[T]
    def returnsMT[M[_], T](v: T): M[T]
}
// We can now write 
val aMock = mock[Foo]
whenF(aMock.returnsOption(*)) thenReturn "mocked!"
whenF(aMock.returnsMT[Future, String](*)) thenReturn "mocked!"
// Rather than
when(aMock.returnsOption(*)) thenReturn Some("mocked!")
when(aMock.returnsMT[Future, String](*)) thenReturn Future.successful("mocked!")

//We could also do stubbings in a single line if that's all we need from the mock
val inlineMock: Foo = whenF(mock[Foo].returnsOption(*)) thenReturn "mocked!"

// For errors we can do
type ErrorOr[A] = Either[Error, A]
val failingMock: Foo = whenF(mock[Foo].returnsMT[ErrorOr, MyClass](*)) thenFailWith Error("error")
//Rather than
val failingMock: Foo = when(mock[Foo].returnsMT[ErrorOr, MyClass](*)) thenReturn Left(Error("error"))

The trait also provides and implicit conversion from scalaz.Equal to scalactic.Equality so if you have an implicit scalaz.Equal instance in scope, it will be automatically used by the eqTo matcher.

IdiomaticMockitoScalaz

Similar to MockitoScalaz but for the idiomatic syntax (including the conversion from scalaz.Equal to scalactic.Equality), so the code would look like

trait Foo {
    def returnsOption[T](v: T): Option[T]
    def returnsMT[M[_], T](v: T): M[T]
}
// We can now write 
val aMock = mock[Foo]
aMock.returnsOption(*) returnsF "mocked!"
aMock.returnsMT[Future, String](*) returnsF "mocked!"
// Rather than
aMock.returnsOption(*) returns Some("mocked!")
aMock.returnsMT[Future, String](*) returns Future.successful("mocked!")

//We could also do stubbings in a single line if that's all we need from the mock
val inlineMock: Foo = mock[Foo].returnsOption(*) returnsF "mocked!"

// For errors we can do
type ErrorOr[A] = Either[Error, A]
val failingMock: Foo = mock[Foo].returnsMT[ErrorOr, MyClass](*) raises Error("error")
//Rather than
val failingMock: Foo = mock[Foo].returnsMT[ErrorOr, MyClass](*) returns Left(Error("error"))

Mocking Scala object

Since version 1.16.0 it is possible to mock object methods, given that such definitions are global, the way to mock them is slightly different in order to ensure we restore the real implementation of the object after we are done

To enable withObjectMocked feature, it is mandatory to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:

 mock-maker-inline

Example:

object FooObject {
  def simpleMethod: String = "not mocked!"
}

"mock" should {
    "stub an object method" in {
      FooObject.simpleMethod shouldBe "not mocked!"

      withObjectMocked[FooObject.type] {
        FooObject.simpleMethod returns "mocked!"
        //or
        when(FooObject.simpleMethod) thenReturn "mocked!"

        FooObject.simpleMethod shouldBe "mocked!"
      }

      FooObject.simpleMethod shouldBe "not mocked!"
    }
}

As you can see, the effect of the mocking is only available inside the code block passed to withObjectMocked, when such block ends the behavior of the object is restored to its original implementation

Notes

Dead code warning

if you have enabled the compiler flag -Ywarn-dead-code, you will see the warning dead code following this construct when using the any or * matchers , this is because in some cases the compiler can not infer the return type of those matchers and it will default to Nothing, and this compiler warning is shown every time Nothing is found on our code. This will NOT affect the behaviour of Mockito nor your test in any way, so it can be ignored, but in case you want to get rid of it then you have 2 options:

  1. If you are not too fuss about dead code warnings in test code, you can add scalacOptions in Test -= "-Ywarn-dead-code" to your build.sbt and that warning will be ignored for your tests only
  2. If you wanna keep the warning enabled for potentially real dead code statements, but get rid of the warnings related to the matchers usage then you have to explicitly provide the type for the matcher, thus any would become any[MyType] and * would become *[MyType] (you can also use anyShort, anyInt, etc for the primitive types)

Scala 2.11

Please note that in Scala 2.11 the following features are not supported

  • Default arguments on methods defined in traits (they will behave as before, getting null or a default value if they are of a primitive type)
  • Any kind of ArgumentMatcher[T] for methods with by-name parameters (they'll throw an exception if used with ArgumentMatcher[T])

Authors

  • Bruno Bonanno - Initial work - bbonanno

License

This project is licensed under the MIT License - see the LICENSE file for details

mockito-scala's People

Contributors

avelx avatar bastaware avatar dangerousben avatar darrenbishop avatar einholen avatar evertones avatar gursahibsahni avatar ingemaradahl avatar jkugiya avatar jozic avatar jsoref avatar keyno63 avatar kluen avatar krever avatar magnolia-k avatar mockitoguy avatar perok avatar rperezlainez avatar scala-steward avatar sethtisue avatar shestee avatar shipkit-org avatar sullis avatar timvdlippe avatar trompa avatar ultrasecreth avatar veysiertekin avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mockito-scala's Issues

Support for value type argument matchers

Is there any way it would be possible to get out-of-the-box support for value types in argument matchers? Ie. allowing me to write eg. any[MyType] instead of MyType(any[Int])

That would be really nice!

Match failure with varargs and multiple parameter lists

Mocking with varargs works as expected:

trait FooWithVarArg {
  def bar(bells: String*) 
}

val foo = mock[FooWithVarArg]

foo.bar("cow", "blue")
foo.bar("cow", "blue") was called // true

foo.bar("cow")
foo.bar("cow") was called // true

So does mocking with a second parameter list:

trait FooWithSecondParameterList {
  def bar(bell: String)(cheese: Cheese) 
}

val foo = mock[FooWithSecondParameterList]
val cheese = new Gouda

foo.bar("cow")(cheese)

foo.bar("cow")(cheese) was called // true
foo.bar("cow")(*) was called // true

But I can't seem to combine varargs with a second parameter list:

trait FooWithBoth {
  def bar(bells: String*)(cheese: Cheese)
}

val foo = mock[FooWithBoth]
val cheese = new Gouda

foo.bar("cow")(cheese)
foo.bar("cow")(cheese) was called // true
foo.bar("cow")(*) was called // false

Instead, I get a match failure:

Argument(s) are different! Wanted:
foo.bar(
    eqTo(cow),
    <any>
);
-> at ...
Actual invocation has different arguments:
foo.bar(
    WrappedArray(cow),
    Cheese
);

Is there some way to match varargs in the first parameter list while ignoring the second parameter list?

warn "dead code following this construct" when using * or any

I'm not sure if thats due to my config but whenever I try to use any or * without specyfing type parameters I get

[error] Foo.scala: dead code following this construct
[error]       foo.bar(*).shouldReturn(List())
[error]               ^

This happens because compiler infers it to Nothing. I'm not sure if it can be fixed though...

Workaround for now is to add the following to build.sbt

scalacOptions in Test -= "-Ywarn-dead-code",

Testing a trait while mocking abstract

I am trying to test a trait that has concrete and abstract methods. I would like to test the concrete methods and mock the abstract methods. When I do this, I get an exception:

An exception or error caused a run to abort: java.lang.Object.concreteMethod(Ljava/lang/Object;)Z 
java.lang.NoSuchMethodError: java.lang.Object.concreteMethod(Ljava/lang/Object;)Z
	at com.verisign.ie.styx.cassandra.tables.TestingTraitsTest.$anonfun$new$1(TestingTraitsTest.scala:21)
	at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:12)
	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
	at org.scalatest.Transformer.apply(Transformer.scala:22)
	at org.scalatest.Transformer.apply(Transformer.scala:20)
	at org.scalatest.FunSuiteLike$$anon$1.apply(FunSuiteLike.scala:186)
	at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)

Here is example code:

trait TestingTraits {
  
  def myAbstractMethod(arg:Object): Boolean

  def concreteMethod(arg: Object): Boolean = {
    myAbstractMethod(arg)
  }
}

and the test:

class TestingTraitsTest extends FunSuite with MockitoSugar with GivenWhenThen {

  test("record not in cache, not in database") {
    case class TestRecord()

    val arg = TestRecord()
    val mockTrait = mock[TestingTraits]

    mwhen(mockTrait.myAbstractMethod(arg)).thenReturn(true)


    mwhen(mockTrait.concreteMethod(same(arg))).thenCallRealMethod()
    mockTrait.concreteMethod(arg)

    verify(mockTrait.myAbstractMethod(arg))
  }
}

Is there any way to get this working? Thanks!

MockitoFixture cannot be used with ResetMocksAfterEachTest

overriding method withFixture in trait MockitoFixture of type (test: IdentificationServiceSpec.this.NoArgTest)org.scalatest.Outcome;
method withFixture in trait ResetMocksAfterEachTest of type (test: IdentificationServiceSpec.this.NoArgTest)org.scalatest.Outcome has weaker access privileges; it should be public

sorry that I only report issues instead of fixing them immediately in a PR, Im low on time ;/

Fix Maven pom problems

Generated pom.xml file should meet all requirements of Maven Central. Here's the validation error I saw when attempting to sync mockito-scala to central:

Last Sync Errors: Invalid POM: /org/mockito/mockito-scala_2.12/0.0.5/mockito-scala_2.12-0.0.5.pom: Project URL missing, License information missing, SCM URL missing, Developer information missing Dropping existing partial staging repository.

@bbonanno, can you take a look at it? Thanks!

HttpExt.singleRequest with implicit parameters can not be mocked

If I try to mock the object HttpExt (imported like this import akka.http.scaladsl.HttpExt) it will not work with this library.
This one will mock the object

import akka.http.scaladsl.HttpExt
import org.scalatest.mockito.MockitoSugar.mock
...

val mockHttp = mock[HttpExt]

this one will not work i.e. it will just return an instance of HttpExt and not a mock

import akka.http.scaladsl.HttpExt
import org.mockito.MockitoSugar.mock

...

val mockHttp = mock[HttpExt]

I also could not spy an HttpExt instance.

I am using

"org.mockito" % "mockito-scala_2.12" % "1.0.1"

and

"org.scalatest" % "scalatest_2.12" % "3.0.5" % "test"

Version 1.x.x

The aim of this release is to provide an overhauled API that removes all usages of the Java API
We'll try to be as backwards compatible as possible, but they may be some breaking changes

  • Wrap every Java object returned by Mockito in a Scala class
  • Try to unify ArgumentMatcher[T] and standard arguments with the new API
  • Design a stable and scalable API

Ongoing work will go to the branch release/1.x

Strict Stub with AsyncIdiomaticMockito

I want to create a unit test to test futures using AsyncWordSpec. I want to use Strict Stub method to reduce mocking boilerplate, following this example here. But I found that it is only available when using WordSpec. Is there anyway to do this asynchronously?

Answers.RETURNS_DEEP_STUBS broken in 0.4.2

Hey, I would love to be able to tell more, but for now all I know is that my code that relied on

val mymock = mock[MyClass](Answers.RETURNS_DEEP_STUBS)
when(myMock.someMethod.foo(any)).thenReturn(null)

is no longer working. Im using MockitoFixture. The error I get in the newest version:

The following invocations are unexpected (click to navigate to relevant line of code):
1. mymock.someMethod(); -> at [...]
Please make sure you aren't missing any stubbing or that your code actually does what you want
org.mockito.exceptions.misusing.UnexpectedInvocationException: Unexpected invocations found

This is probably somehow related to new default-default-answer but I didint have time to investigate.

Conflicting versions of ArgumentsProcessor in mockito-core and mockito-scala

org.mockito.internal.invocation.ArgumentsProcessor class exists in both mockito-core and mockito-scala projects with different API.

Since classloading order is unreliable both versions can be loaded. As a result, when mockito-core's version gets loaded first, there will be errors

java.lang.NoSuchFieldError: extractors
     at org.mockito.ReflectionUtils$.markMethodsWithLazyArgs(ReflectionUtils.scala:19)
     at org.mockito.MockitoEnhancer.mock(MockitoSugar.scala:122)
     at org.mockito.MockitoEnhancer.mock$(MockitoSugar.scala:119)

Please consider moving or renaming mockito-scala's version.

Difference between ShouldReturn and WillBe returned by

When stubbing I always use willBe, however now that I need to chain calls, I see that does not exist in the willBe but just in the shouldReturn option. I wonder what is the difference between both? Because shouldReturn sounds more like an assertion instead of a stubbing

Return different values when using "willBe returned by"

I am just learning mockito-scala, and I am trying to apply the idiomatic style guided by the project documentation.

For some tests, I need to make a spy return different values for each invocation, in order to verify that a retry mechanism is working (i.e., I want to verify that my application will keep trying until an "OK" response is returned by an external system.)

On the documentation, I can see that the idiomatic syntax would allow me to do that with shouldReturn:

aMock.bar shouldReturn "mocked!" andThen "mocked again!"

But I cannot find an example on the documentation (or elsewhere) about how to do that with willBe returned by, which is the specific style I have been using successfully in my test cases. Here's the example provided by the documentation for a single return value:

"mocked!" willBe returned by aMock.bar

Is it possible to have the spy return a different value for each invocation when using willBe returned by? If it is, perhaps a corresponding example could be added to the documentation, or else a note indicating that it is not feasible.

`was never called` overload has limitations

Writing something like

      aMock.doSomethingWithThisIntAndString(*, "test") was never called
      aMock.doSomethingWithThisIntAndString(*, "test") was never called

doesn't compile

while

      aMock.doSomethingWithThisIntAndString(*, "test") was never called
   // line break is required to compile
      aMock.doSomethingWithThisIntAndString(*, "test") was never called

compiles fine

image

Spying on nongeneric subtype of generic type in Scala results in NPE when value type is used as actual type parameter

Summary

Duplicate of mockito/mockito#1605

This simple example produces a NPE on Linux (but apparently not on Mac OS). The key ingredients seem to be:

  • SUT is a nongeneric implementation of a generic type (trait or class)
  • actual type parameter is a value type
  • method to be verified through spy returns that value type
trait A[+E] { def m(): E }
class B extends A[Int] { def m() = -1 }

val s = spy(new B)
verify(s, never).m() // <-- on Linux this fails with NPE in m() above

[error] Test SimpleTest.test failed: java.lang.NullPointerException: null, took 0.617 sec
[error]     at org.mockito.codegenB$MockitoMock$1006795197.m(Unknown Source)

The error goes away when replacing Int with a reference type, such as Integer.

Environment

  • Linux 4.15
  • Oracle Java 11
  • Scala 2.12.x
  • sbt 1.2.x
  • Mockito 2.x (no difference between core and inline)

Working example

https://github.com/klaeufer/mockito-issue-spy-scala
https://travis-ci.org/klaeufer/mockito-issue-spy-scala

`AccessControlException` thrown when using Mockito.spy(...)

Hi I'm getting the following error message when spying on a org.apache.spark.streaming.scheduler.StreamingListener:

 java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")

The issue could be solved by adding the following line to your /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/jre/lib/security/java.policy file -> permission javax.management.MBeanTrustPermission "register"; under the grant section.

I was wondering if there was a programatic solution.

Macro expansion failure with HigherKinds

I use helpers in my tests to keep things clean such as:

def whenGetById[F[_]](implicit algebra: MyAlgebra[F]): OngoingStubbing[F[Either[MyError, MyResult]]] =
    when(algebra.get(anyVal[My.Id])).delegate

// or on later versions
def whenGetById[F[_]](implicit algebra: MyAlgebra[F]): OngoingStubbing[F[Either[MyError, MyResult]]] =
    when(algebra.get(any[My.Id])).delegate

This worked fine from 0.4.4 (obviously without the delegate call) to 1.0.2. However upon upgrading to any version past 1.0.3 my tests now fail to compile:

[error] /***/MockServices.scala:15:46: exception during macro expansion: 
[error] scala.ScalaReflectionException: type F is not a class
[error]         at scala.reflect.api.Symbols$SymbolApi.asClass(Symbols.scala:272)
[error]         at scala.reflect.api.Symbols$SymbolApi.asClass$(Symbols.scala:272)
[error]         at scala.reflect.internal.Symbols$SymbolContextApiImpl.asClass(Symbols.scala:94)
[error]         at org.mockito.internal.ValueClassExtractor$.materialise(ValueClassExtractor.scala:36)
[error]     when[F[Either[MyError, MyResult]]](merchants.get(anyVal[My.Id])).delegate

Currently I have to work around this with the following method, which allows me to use 1.0.5, but I lost any benefits of using the ScalaOngoingStubbing

private def hkWhen[T](methodCall: T): OngoingStubbing[T] = Mockito.when(methodCall)

I presume this is related to the ValueClassExtractor requirement added to when, which does not work for the F HigherKind.

Moreover, since version 1.0.2? my tests have started spitting out dead code errors on when conditions with value classes -- despite stating the types.

Suppor scalamock-like syntax and implicit verification?

Hey!

I recently started to work on a library that was going to be called mockito4s which rather explains its purpose. It's not yet polished nor published and I see little point in continuing to work on it when we have this awesome alternative.

Having said so one of my main objectives was to expose 2 features inspired ScalaMock library:

  1. Better syntax
    Mockito:
when(mock.method(args))

ScalaMock:

(mock.method _).expects(args)

My idea (2 alternative syntax to benefit from type inference in the biggest amount of cases):

//syntax 1
mock.expectsCall(_.method).withArgs(args)
//syntax 2
mock.exprectsArgs(args).whenCalled(_.method)

the syntax here benefits from extensions methods that are obviously not available in java and couldnt be used in original mockito. It make it easy to benefit from nice type inference in bigger number of cases. Syntax 1 is nice if your method signature is simple, no overloads, no implicit parameters and so on, in such case you can alias any[T] to * and have a nice, concise way of mocking. Its fails though when you hit one of the non-trivial cases like multiple parameter lists or overloads. In such a case you can use syntax 2.

Additional benefit of this syntax is that in my implementation the extension methods are available only for types T with MockMarker where MockMarker is an empty marker trait added to type signature coming out of the Mockito.mock wrapper. It makes api more safe by not allowing to setup/verify non-mocks.

  1. Implicit verification
    Explicit verification is extremely boilerplaty in practice and in few years of using ScalaMock I have very rarely found myself veryfing something else then what has ben mocked. That's why I like my mock to synganlize failure automatically if the expected (mocked) method has not been called. When I mock 10 methods with mockito then I need 10 additional lines to make the verification. In majority of cases it duplicates the behaviour.

This feature requires integration with specific testing frameworks, so we can detect single test boundaries and invoke the verification. Its painful from maintenance perspective but extremely useful from the user perspective.

In case it's too far from original mockito ideology we could add verifyAll method that would be called explictly. Maybe it even could be implemented without test framework integration? (I don't know mockito internals good enough)

Also this feature is mostly possible because of the proposed syntax. Im not sure if it can be achieved with the original one.


I have PoC implementation of these features that I would be happy to share. Let me know if you are interested in having these features integrated into mockito-scala. I would love to see that! If not then I will just come up with a wrapper around mockito-scala, because mentioned problems (syntax and explicit verification) caused me a hell lot of pain in the past.

Verification on mock object not respect to test case

Problem:

Let's say we have two different service

class ServiceA(serviceB: ServiceB) {

  def methodA(): String = {
    "methodA called"
    serviceB.methodB()
  }

  def methodA2(): String = {
    "methodA2 called"
    serviceB.methodB()
  }
}

I write two test method and try to verify methodB called or not. When I run two test cases separately, tests pass. When I run all test methods, verification gives wrong result for second test.
In test class context, mockito-verification records all calls on mock object. I think mockito-scala should reset verification counts on mock objects after each test

class ServiceATest extends FlatSpec with IdiomaticMockito {
  val serviceB: ServiceB = mock[ServiceB]
  val serviceA: ServiceA = new ServiceA(serviceB)
  "methodA" should "called" in {
    serviceA.methodA()
    serviceB.methodB wasCalled once // Passes
  }
  "methodA2" should "called" in {
    serviceA.methodA2()
    serviceB.methodB wasCalled once // Fail. it was 2 times:
  }
}

Btw I tried with mockito-core, it gives same error.

Not able to use mock[] with type constructors

I tried to use IdiomaticMockitoFixture with monix.eval.Task which resulted in ClassCastException

Here is a minimized example:
File1.scala:

import org.mockito.IdiomaticMockito

object File1 extends IdiomaticMockito {

  trait Algebra[T] {
    def operation: T
  }

  class Foo

  //We cannot mock type constructors directly
  trait TestAlgebra extends Algebra[Foo]

  def main(args: Array[String]): Unit = {
    val m = mock[TestAlgebra]
    m.operation.shouldReturn(new Foo)
    ()
  }

}

Result:

Exception in thread "main" java.lang.ClassCastException: org.mockito.codegen.Object$MockitoMock$1394191462 cannot be cast to File1$Foo
	at File1$TestAlgebra$MockitoMock$1095682068.operation(Unknown Source)
	at File1$TestAlgebra$MockitoMock$1095682068.operation(Unknown Source)
	at File1$.main(File1.scala:16)
	at File1.main(File1.scala)

If I make Algebra not parametrized or use Mockito.mock. My blind guess is that it has something to do with proxies used for smart null pointers.

can't create mock

Stuck here right out of the gate (using 4.1.0):

package whatever

import org.mockito.MockitoSugar
import org.scalatest.WordSpec

trait Foo {
  def bar: String
  def bar(v: Int): Int
}

class MockSpec extends WordSpec with MockitoSugar {

  val aMock: Foo = mock[Foo]

  "My mock" should {
    "do something useful" in {
      println("look I'm a spec")
    }
  }
}

This compiles, but I get an exception when I run the spec:

An exception or error caused a run to abort: org.mockito.internal.creation.MockSettingsImpl.build(Ljava/lang/Class;)Lorg/mockito/mock/MockCreationSettings; 
java.lang.NoSuchMethodError: org.mockito.internal.creation.MockSettingsImpl.build(Ljava/lang/Class;)Lorg/mockito/mock/MockCreationSettings;
	at org.mockito.MockitoEnhancer$class.mock(MockitoAPI.scala:198)
	at whatever.MockSpec.mock(MockSpec.scala:11)
	at org.mockito.MockitoEnhancer$class.mock(MockitoAPI.scala:141)
	at whatever.MockSpec.mock(MockSpec.scala:11)
	at whatever.MockSpec.<init>(MockSpec.scala:13)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at org.scalatest.tools.Runner$.genSuiteConfig(Runner.scala:1422)
	at org.scalatest.tools.Runner$$anonfun$31.apply(Runner.scala:1236)
	at org.scalatest.tools.Runner$$anonfun$31.apply(Runner.scala:1235)
	at scala.collection.immutable.List.map(List.scala:273)
	at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1235)
	at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1011)
	at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1010)
	at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1500)
	at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010)
	at org.scalatest.tools.Runner$.run(Runner.scala:850)
	at org.scalatest.tools.Runner.run(Runner.scala)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)```

What am I doing wrong here?

testing private methods

Hi,

Great framework. Loved knowing about it. But could not figure out how to test private scala methods? Does it support?

Test failures are swallowed by MockitoFixture

Current implementation:

  override def withFixture(test: NoArgTest): Outcome = {
    val session = MockitoScalaSession(name = s"MockitoFixtureSession[${test.name}]")
    val outcome = super.withFixture(test)
    session.finishMocking()
    outcome
  }

If outcome is a failed test and we have unused stubbings because of it then session.finishMocking() will throw an exception and the original test failure wont be presented to the user.

Public release of mockito-scala

This ticket tracks work needed to release mockito-scala

  • - @bbonanno, can you make the artifacts in "target" directory have the dir structure as expected in a Maven repository? It is needed so that when we publish to Bintray the artifacts will be neatly resolvable by ivy/SBT, Maven or Gradle.
  • - @mockitoguy - configure Bintray publications
  • - @mockitoguy - update the README (if needed)
  • - push & announce

ScalaTest AsyncWordSpec and wasCalled

The AsyncWordSpec trait in scalatest expects a return type of Future[Assertion], but some of the IdiomaticMockito matchers return type Unit (for example, foo.bar wasCalled once), which makes them unusable ("Expression of type Unit does not conform to expected type Assertion").

Serialization of specs2 mocks

I want to use a mock in a Spark Spec but suffered from the same NotSerializableException: org.mockito.internal.creation.DelegatingMethod.

I am trying to follow your guidance in the QA https://stackoverflow.com/questions/53820877/spark-scala-mocking-task-not-serializable

I have switched to mockito-scala and have the following skeleton:

import org.mockito.Mockito
import org.mockito.specs2.{Mockito => Specs2Mockito}
.
.
class MySpec extends SparkSpec with Specs2Mockito {
.
.
val mockedMerlin: Merlin = mockMerlin
.
.
}

but now I get java.io.NotSerializableException: org.mockito.IdiomaticMockitoBase$Answered$

spyLambda can only be used once

Both of the below examples fail the second testcase whereas the first passes:

package x

import org.mockito.MockitoSugar._
import org.scalatest.{BeforeAndAfterEach, FlatSpec}

class SpyLambdaExample1 extends FlatSpec {
  it should "one" in {
    val f = spyLambda { _: Int => 1 }
    f(1)
    verify(f)
  }

  it should "two" in {
    val f = spyLambda { _: String => "2" }
    f("2")
    verify(f)
  }
}

class SpyLambdaExample2 extends FlatSpec with BeforeAndAfterEach {
  private val f = spyLambda { _: Int => 1 }

  override def beforeEach(): Unit = {
    reset(f)
  }

  it should "one" in {
    f(1)
    verify(f)
  }

  it should "two" in {
    f(2)
    verify(f)
  }
}

Can not capture argument with ArgCaptor[Any]

With the following version:

  • mockito-scala: v1.2.4
  • mockito: 2.24.0
  • Scala: 2.12.4

An ArgCaptor[Any] fails to capture, but ArgumentCaptor.forClass[Any, Any](classOf[Any]) is fine.

The below fails at runtime:

val ac5 = ArgCaptor[Any]
verify(scheduler).scheduleOnce(any[Duration], eqTo(topicActor), ac5)(any[ExecutionContext], any[ActorRef])

// Emits the following exception
   Invalid use of argument matchers!
   5 matchers expected, 4 recorded:

// This can be fixed by replacing ac5 with any[Any].
// But I need to capture that argument and validate.

Details

The method signature of scheduleOnce as the below.
There're override variances, but this is the one with correct argument count and type.
The source code of this method can be found here.

  final def scheduleOnce(
    delay:    FiniteDuration,
    receiver: ActorRef,
    message:  Any)(implicit
    executor: ExecutionContext,
                   sender: ActorRef = Actor.noSender): Cancellable

Workaround

// The generic type has to be explicit otherwise it won't compile
val ac5a = ArgumentCaptor.forClass[Any, Any](classOf[Any])

verify(scheduler).scheduleOnce(any[Duration], eqTo(topicActor), ac5a.capture())(any[ExecutionContext], any[ActorRef])

Constructor Injected Class Instance Variable Loses Mocking doThrow or doReturn Doesn't work

I have a spring boot application and am using MockitoSugar to write tests.
Spring boot version: 2.0.5.RELEASE
Scala version: 2.11.8
mockito-scala_2.11: 1.2.4

Injecting mock in constructor:

 val headerParamsResolverMock = mock[HeaderParamsResolver]
 val irsArgumentResolver = new IRSArgumentResolver(headerParamsResolverMock)

Test Case:

"resolverArgument" should "invoke resolve method if header parameter is not resolved" in {
val parameter = mock[Parameter]
doReturn(parameter, Nil: _*).when(methodParameterMock).getParameter
doReturn("string", Nil: _*).when(parameter).getName
doReturn(false, Nil: _*).when(headerParamsResolverMock).isResolved
doReturn("string", Nil: _*).when(headerParamsResolverMock).resolve(mock[NativeWebRequest]) // doesn't work


irsArgumentResolver.resolveArgument(methodParameterMock, mock[ModelAndViewContainer], mock[NativeWebRequest],
    mock[WebDataBinderFactory])

Mockito.verify(headerParamsResolverMock).resolve(mock[NativeWebRequest])
}

Class under test

 @Component
 public final class IRSArgumentResolver implements HandlerMethodArgumentResolver {

private HeaderParamsResolver headerParamsResolver;

public IRSArgumentResolver(HeaderParamsResolver headerParamsResolver) {
    this.headerParamsResolver = headerParamsResolver;
 }
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                              WebDataBinderFactory binderFactory) {

    String sample = "";
    if (!headerParamsResolver.isResolved())
        sample = headerParamsResolver.resolve(webRequest);

    System.out.println(sample); // here its null 
    return webRequest.getParameter(parameter.getParameter().getName());
}

}

If I see the debugger, the headerParamsResolver isn't shown as a mock object like other method parameters show up. Like Mock for Method Paramater OR Mock for ModelAndViewContainer etc. Moreover, only the isResolved class instance variable is set but other mock features like doThrow or doReturn doesn't work. PFA debugger screen.

Screen Shot 2019-04-03 at 1 57 10 PM

Moreover, this test case throws exception:
Screen Shot 2019-04-03 at 2 28 23 PM

Scalactic integration

Check if we can integrate matchers with Scalactic so we can reuse the type classes of === and the like

Mocking any instance of class

Less of an issue and more of a question: Is it possible to mock any instance of a class, not just a single instance?

Use case here is that I have a class with a copy method that creates a new instance of the class with extra members. I want to be able to spy on copied instances that are created inside of various functions.

stubbing real object is silently ignored

Following code throws a nice exception as expected:

import org.mockito.IdiomaticMockito
import org.scalatest.FunSuite

class Foo {
  def bar(x: String): String = x
}

class TestTest extends FunSuite with IdiomaticMockito {
  val x = new Foo
  x.bar("x").shouldReturn("XXXX")
}

But if we add at least one successfully created mock at the beginning it runs ok:

import org.mockito.IdiomaticMockito
import org.scalatest.FunSuite

class Foo {
  def bar(x: String): String = x
}

class TestTest extends FunSuite with IdiomaticMockito {
  val y = mock[Foo]
  y.toString // fool warn-unused

  val x = new Foo
  x.bar("x").shouldReturn("XXXX")
}

It was extremely hard to identify the problem and minimize :D

ArgCaptor results in NullPointerException when trying to access value

My code is of the form:

val thingsCaptor = ArgCaptor[Seq[Thing]]
verify(someMock).doStuff(thingsCaptor)

When I try to access the value in any way, even by doing a toSeq, I get a NullPointerException. I know that something should be captured, since I can get a valid value if I use the standard Mockito ArgumentCaptor.forClass approach.

It's a shame, because I really like the new syntax. :)

0.3.1 Mock creation in `thenReturn` fails (works with scalatest mockitosugar)

So I have a weird error that I've tried to narrow down to a simple scenario. Basically If I try to create a mock in the thenReturn method of stubbing it fails at runtime. It works if the mock is created before and also works if I'm using the scala test mockito sugar, not really sure what is going on here.

package example

import org.mockito.MockitoSugar
import org.scalatest.WordSpec

case class AClass(property: Set[String])

class DoStuff {

    def doMethod(): AClass = {
        // we are going to mock this anyway
        ???
    }
}

class MockitoScalaSpec extends WordSpec with MockitoSugar {

    "Mock works" in {
        val a = mock[AClass]
        val worker = mock[DoStuff]
        when(worker.doMethod()).thenReturn(a)

    }

    "Mock inside then return doesn't work" in {
        val worker = mock[DoStuff]
        when(worker.doMethod()).thenReturn(mock[AClass])

    }

    "Does work for scala test inside then return doesn't work" in {
        val worker = org.scalatest.mockito.MockitoSugar.mock[DoStuff]
        when(worker.doMethod()).thenReturn(org.scalatest.mockito.MockitoSugar.mock[AClass])

    }

}

Only Mock inside then return doesn't work and it fails with


Calling public scala.collection.immutable.Set example.AClass$MockitoMock$676536933.copy$default$1() on Mock for AClass, hashCode: 585074510 with args []
java.lang.RuntimeException: Calling public scala.collection.immutable.Set example.AClass$MockitoMock$676536933.copy$default$1() on Mock for AClass, hashCode: 585074510 with args []
	at org.mockito.MockitoEnhancerUtil.call(MockitoEnhancerUtil.java:67)
	at org.mockito.MockitoEnhancerUtil.lambda$stubDefaultMethods$4(MockitoEnhancerUtil.java:56)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at org.mockito.MockitoEnhancerUtil.stubDefaultMethods(MockitoEnhancerUtil.java:56)
	at org.mockito.MockitoEnhancerUtil.stubAllDefaultMethods(MockitoEnhancerUtil.java:49)
	at org.mockito.MockitoSugar.stubMock(MockitoSugar.scala:4)
	at org.mockito.MockitoSugar.stubMock$(MockitoSugar.scala:4)
	at example.MockitoScalaSpec.stubMock(MockitoScalaSpec.scala:16)
	at org.mockito.MockitoEnhancer.mock(MockitoAPI.scala:144)
	at org.mockito.MockitoEnhancer.mock$(MockitoAPI.scala:137)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	at org.mockito.MockitoEnhancer.mock(MockitoAPI.scala:104)
	at org.mockito.MockitoEnhancer.mock$(MockitoAPI.scala:104)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	at example.MockitoScalaSpec.$anonfun$new$2(MockitoScalaSpec.scala:27)
	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
	at org.scalatest.Transformer.apply(Transformer.scala:22)
	at org.scalatest.Transformer.apply(Transformer.scala:20)
	at org.scalatest.WordSpecLike$$anon$1.apply(WordSpecLike.scala:1078)
	at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
	at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
	at org.scalatest.WordSpec.withFixture(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.invokeWithFixture$1(WordSpecLike.scala:1076)
	at org.scalatest.WordSpecLike.$anonfun$runTest$1(WordSpecLike.scala:1088)
	at org.scalatest.SuperEngine.runTestImpl(Engine.scala:289)
	at org.scalatest.WordSpecLike.runTest(WordSpecLike.scala:1088)
	at org.scalatest.WordSpecLike.runTest$(WordSpecLike.scala:1070)
	at org.scalatest.WordSpec.runTest(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.$anonfun$runTests$1(WordSpecLike.scala:1147)
	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:396)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:379)
	at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:461)
	at org.scalatest.WordSpecLike.runTests(WordSpecLike.scala:1147)
	at org.scalatest.WordSpecLike.runTests$(WordSpecLike.scala:1146)
	at org.scalatest.WordSpec.runTests(WordSpec.scala:1881)
	at org.scalatest.Suite.run(Suite.scala:1147)
	at org.scalatest.Suite.run$(Suite.scala:1129)
	at org.scalatest.WordSpec.org$scalatest$WordSpecLike$$super$run(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.$anonfun$run$1(WordSpecLike.scala:1192)
	at org.scalatest.SuperEngine.runImpl(Engine.scala:521)
	at org.scalatest.WordSpecLike.run(WordSpecLike.scala:1192)
	at org.scalatest.WordSpecLike.run$(WordSpecLike.scala:1190)
	at org.scalatest.WordSpec.run(WordSpec.scala:1881)
	at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45)
	at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13(Runner.scala:1346)
	at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13$adapted(Runner.scala:1340)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1340)
	at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24(Runner.scala:1031)
	at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24$adapted(Runner.scala:1010)
	at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1506)
	at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010)
	at org.scalatest.tools.Runner$.run(Runner.scala:850)
	at org.scalatest.tools.Runner.run(Runner.scala)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.mockito.MockitoEnhancerUtil.call(MockitoEnhancerUtil.java:64)
	... 68 more
Caused by: org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at example.MockitoScalaSpec.when(MockitoScalaSpec.scala:16)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at example.MockitoScalaSpec.stubMock(MockitoScalaSpec.scala:16)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	... 47 more



Using

object Dependencies {
  lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5"
  lazy val mockitoScala = "org.mockito" %% "mockito-scala" % "0.3.1"
}

ReturnsSmartNulls returns empty string for `String` return type

When you mock method returning String and doesnt stub it, then you get empty stirng instead of null.
Example:

class Test extends FunSuite with MockitoFixture {
  trait Foo {
    def foo: String
    def bar: Object
  }

  test("should faill") {
    val f1 = mock[Foo](DefaultAnswers.ReturnsSmartNulls)
    val f2 = Mockito.mock(classOf[Foo])
    println(f1.foo + "xxx")
    println(f1.bar + "xxx")
  }
}

this prints:

xxx
nullxxx

Its unsafe because one can forget about stubbing when not using MockitoFixture + its irregular.

Feature request: unify matchers and raw values

This was discussed in core mockito here: mockito/mockito#1398 but it doesnt seem to be available soon.

Considering that with mockito-scala we don't have to care about compatibility maybe we can somehow implement this feature here?

Its so annoying I would even consider spending some time on implementing this during the weekend but I don't have a good idea on how to achieve this. Any help/ideas would be welcome.

Documentation for mockito-core and mockito-scala dependency order

I just saw mock[X] randomly working and not (ArgumentsProcessor.extractors not found) which seems to be related to mockito-scala overwriting that class.

If I remember correctly to make this work the mockito-core dependency has to be declared explicitly before the mockito-scala dependency like

libraryDependencies ++= Seq(
  "org.mockito"              % "mockito-core"             % "2.21.0" % Test,      
  "org.mockito"              %% "mockito-scala"         % "0.0.13" % Test
)

Maybe I am missing something but if my assumption is right I suggest to add that information to the readme to avoid others running into the same issue.

Mocktio sugar failing to create mock for restclient

Hi,
I am trying to mock a library called restclient. When I try to use the mocktio sugar syntax mock(RestClient), the test fails with the following message

[ERROR] C:\work\aeegerrit\artisan\src\test\scala\org\onap\aai\mosaic\query\QueryTest.scala:20: error: class org.onap.aai.restclient.client.RestClient is not a value
[ERROR] val stubbedRestClient: RestClient = mock(RestClient)

After going though the issues, I found this issue
#45
and tried using
val stubbedRestClient: RestClient = Mockito.mock(classOf[RestClient])
and I was able to create the mock object and use it.

I am not sure if this is an issue with the restLibrary that I am using or the version of mockito-scala library

More Information
mockito-scala version: mockito-scala_2.12: 1.1.4
RestClient library : https://gerrit.onap.org/r/#/admin/projects/aai/rest-client
Class that I am trying to mock: https://gerrit.onap.org/r/gitweb?p=aai/rest-client.git;a=blob;f=src/main/java/org/onap/aai/restclient/client/RestClient.java;h=89d5c62d9596c147e9bba5bdfa2ec4cd0151b477;hb=refs/heads/master

BaseSpec which imports MockitoSugar that I extend into all my tests

import java.io.FileInputStream
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest._
import org.mockito.{MockitoSugar, ArgumentMatchersSugar}

@RunWith(classOf[JUnitRunner])
abstract class BaseTestSpec extends FlatSpec with Matchers with
OptionValues with Inside with Inspectors with TryValues with MockitoSugar with ArgumentMatchersSugar

Thanks for the lovely mocking library. This helped me to mock overloaded java functions which scalamock has issues with.

Any help is greatly appreciated.

"illegal cyclic reference involving object Suggest" When Trying to Mock RestHighLevelClient

Hi,

When I tried to mock Elasticsearch's RestHighLevelClient (6.4.0) I encountered the following excption

By the way, my mockito-scala version is 0.4.5

illegal cyclic reference involving object Suggest scala.reflect.internal.Symbols$CyclicReference: illegal cyclic reference involving object Suggest at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1523) at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1521) at scala.Function0$class.apply$mcV$sp(Function0.scala:34) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.reflect.internal.Symbols$Symbol.lock(Symbols.scala:567) at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1521) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:123) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.info(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$coreLookup$1(JavaMirrors.scala:992) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$lookupClass$1(JavaMirrors.scala:998) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$classToScala1(JavaMirrors.scala:1003) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$toScala$1.apply(JavaMirrors.scala:97) at scala.reflect.runtime.TwoWayCaches$TwoWayCache$$anonfun$toScala$1.apply(TwoWayCaches.scala:38) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.TwoWayCaches$TwoWayCache.toScala(TwoWayCaches.scala:33) at scala.reflect.runtime.JavaMirrors$JavaMirror.toScala(JavaMirrors.scala:95) at scala.reflect.runtime.JavaMirrors$JavaMirror.classToScala(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1090) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$targToScala$1(JavaMirrors.scala:1072) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$targsToScala$1.apply(JavaMirrors.scala:1074) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$targsToScala$1.apply(JavaMirrors.scala:1074) at scala.collection.immutable.List.map(List.scala:284) at scala.reflect.runtime.JavaMirrors$JavaMirror.targsToScala(JavaMirrors.scala:1074) at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1093) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$13.apply(JavaMirrors.scala:755) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$13.apply(JavaMirrors.scala:755) at scala.collection.immutable.List.map(List.scala:284) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply$mcV$sp(JavaMirrors.scala:755) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.completeRest(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$LazyPolyType.complete(JavaMirrors.scala:798) at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1535) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:123) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.info(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$coreLookup$1(JavaMirrors.scala:992) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$lookupClass$1(JavaMirrors.scala:998) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$classToScala1(JavaMirrors.scala:1003) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$toScala$1.apply(JavaMirrors.scala:97) at scala.reflect.runtime.TwoWayCaches$TwoWayCache$$anonfun$toScala$1.apply(TwoWayCaches.scala:38) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.TwoWayCaches$TwoWayCache.toScala(TwoWayCaches.scala:33) at scala.reflect.runtime.JavaMirrors$JavaMirror.toScala(JavaMirrors.scala:95) at scala.reflect.runtime.JavaMirrors$JavaMirror.classToScala(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1090) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$targToScala$1(JavaMirrors.scala:1072) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$targsToScala$1.apply(JavaMirrors.scala:1074) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$targsToScala$1.apply(JavaMirrors.scala:1074) at scala.collection.immutable.List.map(List.scala:284) at scala.reflect.runtime.JavaMirrors$JavaMirror.targsToScala(JavaMirrors.scala:1074) at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1093) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$13.apply(JavaMirrors.scala:755) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$13.apply(JavaMirrors.scala:755) at scala.collection.immutable.List.map(List.scala:284) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply$mcV$sp(JavaMirrors.scala:755) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.completeRest(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.complete(JavaMirrors.scala:745) at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1535) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:123) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:171) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.info(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$2.info(SynchronizedSymbols.scala:171) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$coreLookup$1(JavaMirrors.scala:992) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$lookupClass$1(JavaMirrors.scala:998) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$classToScala1(JavaMirrors.scala:1003) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$classToScala$1.apply(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$toScala$1.apply(JavaMirrors.scala:97) at scala.reflect.runtime.TwoWayCaches$TwoWayCache$$anonfun$toScala$1.apply(TwoWayCaches.scala:38) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.TwoWayCaches$TwoWayCache.toScala(TwoWayCaches.scala:33) at scala.reflect.runtime.JavaMirrors$JavaMirror.toScala(JavaMirrors.scala:95) at scala.reflect.runtime.JavaMirrors$JavaMirror.classToScala(JavaMirrors.scala:980) at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1085) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$jmethodAsScala1(JavaMirrors.scala:1159) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$scala$reflect$runtime$JavaMirrors$JavaMirror$$jmethodAsScala$1.apply(JavaMirrors.scala:1151) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$scala$reflect$runtime$JavaMirrors$JavaMirror$$jmethodAsScala$1.apply(JavaMirrors.scala:1151) at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$toScala$1.apply(JavaMirrors.scala:97) at scala.reflect.runtime.TwoWayCaches$TwoWayCache$$anonfun$toScala$1.apply(TwoWayCaches.scala:38) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.TwoWayCaches$TwoWayCache.toScala(TwoWayCaches.scala:33) at scala.reflect.runtime.JavaMirrors$JavaMirror.toScala(JavaMirrors.scala:95) at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$jmethodAsScala(JavaMirrors.scala:1151) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$mcV$sp$4.apply(JavaMirrors.scala:782) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$apply$mcV$sp$1$$anonfun$apply$mcV$sp$4.apply(JavaMirrors.scala:782) at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(JavaMirrors.scala:782) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply$mcV$sp(JavaMirrors.scala:791) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter$$anonfun$completeRest$1.apply(JavaMirrors.scala:749) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.completeRest(JavaMirrors.scala:749) at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.complete(JavaMirrors.scala:745) at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1535) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$8.scala$reflect$runtime$SynchronizedSymbols$SynchronizedSymbol$$super$info(SynchronizedSymbols.scala:168) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anonfun$info$1.apply(SynchronizedSymbols.scala:127) at scala.reflect.runtime.Gil$class.gilSynchronized(Gil.scala:19) at scala.reflect.runtime.JavaUniverse.gilSynchronized(JavaUniverse.scala:16) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:123) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$8.gilSynchronizedIfNotThreadsafe(SynchronizedSymbols.scala:168) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$class.info(SynchronizedSymbols.scala:127) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$8.info(SynchronizedSymbols.scala:168) at scala.reflect.runtime.SynchronizedSymbols$SynchronizedSymbol$$anon$8.info(SynchronizedSymbols.scala:168) at org.mockito.ReflectionUtils$$anon$1.apply(ReflectionUtils.scala:29) at org.mockito.ReflectionUtils$$anon$1.apply(ReflectionUtils.scala:23) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at org.mockito.ReflectionUtils$.markMethodsWithLazyArgs(ReflectionUtils.scala:21) at org.mockito.MockitoEnhancer$class.mock(MockitoAPI.scala:157) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest.mock(VendorItemServiceTest.scala:22) at org.mockito.MockitoEnhancer$class.mock(MockitoAPI.scala:110) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest.mock(VendorItemServiceTest.scala:22) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest$Setup$class.$init$(VendorItemServiceTest.scala:25) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest$$anonfun$1$$anon$1.<init>(VendorItemServiceTest.scala:120) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest$$anonfun$1.apply(VendorItemServiceTest.scala:120) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest$$anonfun$1.apply(VendorItemServiceTest.scala:120) at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85) at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) at org.scalatest.Transformer.apply(Transformer.scala:22) at org.scalatest.Transformer.apply(Transformer.scala:20) at org.scalatest.FlatSpecLike$$anon$1.apply(FlatSpecLike.scala:1682) at org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest.org$mockito$integrations$scalatest$MockitoSessionFixture$$super$withFixture(VendorItemServiceTest.scala:22) at org.mockito.integrations.scalatest.MockitoSessionFixture$class.withFixture(MockitoSessionFixture.scala:10) at com.coupang.sellernudging.bigdata.vendoritem.VendorItemServiceTest.withFixture(VendorItemServiceTest.scala:22) at org.scalatest.FlatSpecLike$class.invokeWithFixture$1(FlatSpecLike.scala:1679) at org.scalatest.FlatSpecLike$$anonfun$runTest$1.apply(FlatSpecLike.scala:1692) at org.scalatest.FlatSpecLike$$anonfun$runTest$1.apply(FlatSpecLike.scala:1692) at org.scalatest.SuperEngine.runTestImpl(Engine.scala:289) at org.scalatest.FlatSpecLike$class.runTest(FlatSpecLike.scala:1692) at org.scalatest.FlatSpec.runTest(FlatSpec.scala:1685) at org.scalatest.FlatSpecLike$$anonfun$runTests$1.apply(FlatSpecLike.scala:1750) at org.scalatest.FlatSpecLike$$anonfun$runTests$1.apply(FlatSpecLike.scala:1750) at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:396) at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:384) at scala.collection.immutable.List.foreach(List.scala:392) at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384) at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:373) at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:410) at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:384) at scala.collection.immutable.List.foreach(List.scala:392) at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384) at org.scalatest.SuperEngine.org$scalatest$SuperEngine$$runTestsInBranch(Engine.scala:379) at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:461) at org.scalatest.FlatSpecLike$class.runTests(FlatSpecLike.scala:1750) at org.scalatest.FlatSpec.runTests(FlatSpec.scala:1685) at org.scalatest.Suite$class.run(Suite.scala:1147) at org.scalatest.FlatSpec.org$scalatest$FlatSpecLike$$super$run(FlatSpec.scala:1685) at org.scalatest.FlatSpecLike$$anonfun$run$1.apply(FlatSpecLike.scala:1795) at org.scalatest.FlatSpecLike$$anonfun$run$1.apply(FlatSpecLike.scala:1795) at org.scalatest.SuperEngine.runImpl(Engine.scala:521) at org.scalatest.FlatSpecLike$class.run(FlatSpecLike.scala:1795) at org.scalatest.FlatSpec.run(FlatSpec.scala:1685) at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45) at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$1.apply(Runner.scala:1346) at org.scalatest.tools.Runner$$anonfun$doRunRunRunDaDoRunRun$1.apply(Runner.scala:1340) at scala.collection.immutable.List.foreach(List.scala:392) at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1340) at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1011) at org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1010) at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1506) at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010) at org.scalatest.tools.Runner$.run(Runner.scala:850) at org.scalatest.tools.Runner.run(Runner.scala) at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131) at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)

My code looks like this
`
package com.coupang.sellernudging.bigdata.vendoritem

import org.elasticsearch.client.{RequestOptions, RestHighLevelClient}
import org.mockito.integrations.scalatest.MockitoFixture
import org.scalatest.FlatSpec

class VendorItemServiceTest1 extends FlatSpec with MockitoFixture {

trait Setup {
val client: RestHighLevelClient = mock[RestHighLevelClient]
}

behavior of "Update items"

it should "insert into empty" in new Setup {

}
}
`
Other mock works perfect, could you please have a look? Thanks a lot.

Malformed class name

When using a case class or case object in the following way

 sealed trait SomeTrait
  object SomeTrait {
    final case object A extends SomeTrait
    final case object B  extends SomeTrait
  }

It crashes when the underlying JVM selected is java-8

with the following stack trace

java.lang.InternalError: Malformed class name
	at java.lang.Class.getSimpleName(Class.java:1330)
	at ru.vyarus.java.generics.resolver.util.TypeToStringUtils.toStringType(TypeToStringUtils.java:42)
	at ru.vyarus.java.generics.resolver.util.TypeToStringUtils.join(TypeToStringUtils.java:189)
	at ru.vyarus.java.generics.resolver.util.TypeToStringUtils.toStringMethod(TypeToStringUtils.java:107)
	at ru.vyarus.java.generics.resolver.context.GenericsContext.method(GenericsContext.java:148)
	at org.mockito.ReflectionUtils$InvocationOnMockOps.$anonfun$resolveWithJavaGenerics$1(ReflectionUtils.scala:56)
	at scala.util.Try$.apply(Try.scala:213)
	at org.mockito.ReflectionUtils$InvocationOnMockOps.resolveWithJavaGenerics(ReflectionUtils.scala:56)
	at org.mockito.ReflectionUtils$InvocationOnMockOps.$anonfun$returnType$1(ReflectionUtils.scala:31)
	at scala.Option.orElse(Option.scala:306)
	at org.mockito.ReflectionUtils$InvocationOnMockOps.returnType(ReflectionUtils.scala:31)
	at org.mockito.stubbing.ReturnsSmartNulls$.$anonfun$apply$1(ReturnsSmartNulls.scala:17)
	at scala.Option.orElse(Option.scala:306)
	at org.mockito.stubbing.ReturnsSmartNulls$.apply(ReturnsSmartNulls.scala:16)
	at org.mockito.stubbing.ReturnsSmartNulls$.apply(ReturnsSmartNulls.scala:12)
	at org.mockito.stubbing.DefaultAnswer.answer(DefaultAnswer.scala:12)
	at org.mockito.stubbing.DefaultAnswer.answer$(DefaultAnswer.scala:12)
	at org.mockito.stubbing.ReturnsSmartNulls$.answer(ReturnsSmartNulls.scala:12)
	at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:103)
	at org.mockito.internal.handler.ScalaMockHandler.handle(ScalaMockHandler.scala:37)
	at org.mockito.internal.handler.ScalaNullResultGuardian.handle(ScalaNullResultGuardian.scala:10)
	at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:35)
	at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:61)
	at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:49)
	at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptAbstract(MockMethodInterceptor.java:126)
	at ExampleSpec$Client$MockitoMock$56560596.apply(Unknown Source)

Changing it to something like this works

 sealed trait SomeTrait
 final case object A extends SomeTrait
 final case object B  extends SomeTrait

You can reproduce it with the following example: https://gist.github.com/umbreak/6c2adaeb67c6488cc7f2438f9459af6f

Feature request: no nulls by default.

In scala code null is rarely used in favour instead of Option.None or for collections an empty collection. As a result the actual code is not checking or expecting null.

This doesn't play well with mockito which returns nulls by default for non-stubbed methods, is it possible to somehow wire up something to change this behaviour inside this framework itself.

So it could default for e.g. any Option[T] into None, List[T] into Nil , etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.