Mockito in specs2 evaluates a by-name functions when using spy

118 visualizações
Pular para a primeira mensagem não lida

Anatoly Rabinovich

não lida,
4 de ago. de 2016, 07:38:3604/08/2016
para specs2-users

I've asked this questions also in: https://stackoverflow.com/questions/38766278/mockito-in-specs2-evaluates-a-by-name-functions-when-using-spy.


I'm trying to understand the behaviour of the 'spy' function in 'Mockito' (specs2), when I'm trying to run the following test code:

import org.specs2.mock.Mockito
import org.specs2.mutable.SpecificationWithJUnit
import org.specs2.specification.Scope

import scala.util.{Failure, Success, Try}

class Foo {
  def foo(f: => Int): Unit = Try { f } match {
    case Success(value) => value
    case Failure(_) => foo1()
  }

  def foo1(): Unit = ???
}

class Boo {
  def boo(): Int = ???
}

class SomeTestClass extends SpecificationWithJUnit {
  "something" should {
    "happen" in new Context {
      mockedBoo.boo returns 1

      spiedFoo.foo(mockedBoo.boo())

      there was one(spiedFoo).foo1
    }
  }
}

trait Context extends Scope with Mockito {
  val spiedFoo = spy(new Foo)

  val mockedBoo = mock[Boo]
}


It seems that when calling:

spiedFoo.foo(mockedBoo.boo())


Mocked boo is evaluated before 'Foo.foo' gets the chance to run it's code. I added a breakpoint inside 'boo' and checked the stacktrace which told me that it was invoked by 'MethodInterceptorFilter'. More specifically by 'ArgumentsProcessor.argumentsToMatchers' which looks like this:

if (!isCallRealMethod) {
  // evaluate the byname parameter to collect the argument matchers
  // if an exception is thrown we keep the value to compare it with the actual one (see "with Any" in the MockitoSpec and issue 82)
  val value = try {
    arg.asInstanceOf[Function0[_]].apply()
  } catch {
    case e: Throwable => e
  }
  // during the evaluation of the value some matchers might have been created. pull them.
  val argumentsMatchers = ThreadSafeMockingProgress2.pullLocalizedMatchers
  // if there are no matchers at all being registered this means that
  // we are invoking the method, not verifying it
  // in that case add a new matcher corresponding to the argument (an equals matcher using the value)
  if (argumentsMatchers.isEmpty) matchers.add(new EqualsFunction0(value))
  else {
    // otherwise we add all the existing arguments matchers +
    // we reset the state of the argumentMatchersStorage
    matchers.addAll(argumentsMatchers.map(_.getActualMatcher))
    ThreadSafeMockingProgress2.reportMatchers(argumentsMatchers.map(_.getActualMatcher))
  }
}


It clearly tells us: "evaluate the byname parameter to collect the argument matchers". How do I avoid the evaluation of the by-name parameter?


Thanks!

etorreborre

não lida,
5 de ago. de 2016, 03:33:4305/08/2016
para specs2-users
Please see my comment on stackoverflow, I think this has been fixed in a more recent version of specs2.

E.
Responder a todos
Responder ao autor
Encaminhar
0 nova mensagem