All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.specs2.mock.mockito.Invocation.scala Maven / Gradle / Ivy

The newest version!
package org.mockito.internal.invocation

/*
 * Copyright (c) 2007 Mockito contributors
 * This program is made available under the terms of the MIT License.
 */

import org.hamcrest.Matcher
import org.mockito.exceptions.PrintableInvocation
import org.mockito.exceptions.Reporter
import org.mockito.internal.debugging.Location
import org.mockito.internal.exceptions.VerificationAwareInvocation
import org.mockito.internal.invocation.realmethod.RealMethod
import org.mockito.internal.reporting.PrintSettings
import org.mockito.internal.reporting.PrintingFriendlyInvocation
import org.mockito.internal.util.MockUtil
import org.mockito.internal.util.ObjectMethodsGuru
import org.mockito.internal.util.Primitives
import org.mockito.invocation.InvocationOnMock
import java.lang.reflect.Method
import java.util.ArrayList
import java.util.Arrays
import java.util.List
import org.mockito.internal.progress.ThreadSafeMockingProgress2

import Invocation.{expandVarArgs, MAX_LINE_LENGTH}
import org.mockito.internal.matchers.{EqualsFunction0, EqualsFunction1, ArrayEquals, Equals, MatchersPrinter}

/**
 * This class redefines Mockito Invocation behavior class when evaluating byname arguments.
 *
 * The only changed method is `argumentsToMatchers`
 */
@SuppressWarnings(Array("unchecked"))
class Invocation extends PrintableInvocation with InvocationOnMock with PrintingFriendlyInvocation with VerificationAwareInvocation {

  def this(mock: AnyRef, mockitoMethod: MockitoMethod, args: Array[AnyRef], sequenceNumber: Int, realMethod: RealMethod) {
    this()
    this.method = mockitoMethod
    this.mock = mock
    this.realMethod = realMethod
    this.arguments = expandVarArgs(mockitoMethod.isVarArgs, args)
    this.rawArguments = args
    this.sequenceNumber = sequenceNumber
    this.location = new Location
  }

  protected def argumentsToMatchers: List[Matcher[_]] = {
    var matchers: List[Matcher[_]] = new ArrayList[Matcher[_]](arguments.length)
    for (arg <- arguments) {
      if (arg != null && arg.getClass.isArray) matchers.add(new ArrayEquals(arg))
      else if (arg != null && arg.getClass.getName.startsWith("scala.collection.mutable.WrappedArray")) matchers.add(new Equals(arg))
      else if (arg.isInstanceOf[Function0[_]]) {
        // 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 => e }
        val argumentsMatchers = ThreadSafeMockingProgress2.pullMatchers
        // if there are no matchers, use the value directly with an equals matcher
        if (argumentsMatchers.isEmpty) matchers.add(new EqualsFunction0(value))
        else                           matchers.addAll(argumentsMatchers)
      }
      else if (arg.isInstanceOf[org.specs2.matcher.Matcher[_]]) {
        matchers.add(new org.specs2.mock.HamcrestMatcherAdapter(arg.asInstanceOf[org.specs2.matcher.Matcher[_]]))
      }
      else if (arg.isInstanceOf[Function1[_,_]]) {
        matchers.add(new EqualsFunction1(arg))
      }
      else matchers.add(new Equals(arg))
    }
    matchers
  }


  def getMock: AnyRef = mock
  def getMethod: Method = method.getJavaMethod
  def getArguments: Array[AnyRef] = arguments
  def isVerified: Boolean = verified || isIgnoredForVerification
  def getSequenceNumber: java.lang.Integer = sequenceNumber

  override def equals(o: Any): Boolean = {
    if (o == null || !(o.getClass == this.getClass)) {
      return false
    }
    var other: Invocation = o.asInstanceOf[Invocation]
    (this.mock == other.mock) && (this.method == other.method) && this.equalArguments(other.arguments)
  }

  private def equalArguments(arguments: Array[AnyRef]): Boolean = Arrays.equals(arguments, this.arguments)
  override def hashCode = 1
  override def toString: String = toString(argumentsToMatchers, new PrintSettings)
  protected def toString(matchers: List[Matcher[_]], printSettings: PrintSettings): String = {
    var matchersPrinter: MatchersPrinter = new MatchersPrinter
    var method: String = qualifiedMethodName
    var invocation: String = method + matchersPrinter.getArgumentsLine(matchers, printSettings)
    if (printSettings.isMultiline || (!matchers.isEmpty && invocation.length > MAX_LINE_LENGTH))
      method + matchersPrinter.getArgumentsBlock(matchers, printSettings)
    else invocation
  }
  private def qualifiedMethodName: String = new MockUtil().getMockName(mock) + "." + method.getName


  def isToString: Boolean = new ObjectMethodsGuru().isToString(getMethod)

  def isValidException(throwable: Throwable): Boolean = {
    var exceptions: Array[Class[_]] = this.getMethod.getExceptionTypes
    var throwableClass: Class[_] = throwable.getClass
    for (exception <- exceptions) {
      if (exception.isAssignableFrom(throwableClass)) {
        return true
      }
    }
    false
  }

  def isValidReturnType(clazz: Class[_]): Boolean = {
    if (method.getReturnType.isPrimitive) {
      Primitives.primitiveTypeOf(clazz) eq method.getReturnType
    }
    else {
      method.getReturnType.isAssignableFrom(clazz)
    }
  }

  def isVoid: Boolean = this.method.getReturnType eq Void.TYPE
  def printMethodReturnType: String = method.getReturnType.getSimpleName
  def getMethodName: String = method.getName
  def returnsPrimitive: Boolean = method.getReturnType.isPrimitive
  def getLocation: Location = location
  def getArgumentsCount: Int = arguments.length
  def getRawArguments: Array[AnyRef] = this.rawArguments
  def callRealMethod: AnyRef = {
    if (isDeclaredOnInterface) new Reporter().cannotCallRealMethodOnInterface
    realMethod.invoke(mock, rawArguments)
  }
  def isDeclaredOnInterface: Boolean = this.getMethod.getDeclaringClass.isInterface
  def toString(printSettings: PrintSettings): String = toString(argumentsToMatchers, printSettings)

  private[invocation] def markVerified { this.verified = true }
  def markStubbed(stubInfo: StubInfo) { this._stubInfo = stubInfo }
  def ignoreForVerification { _isIgnoredForVerification = true }
  def isIgnoredForVerification = _isIgnoredForVerification.booleanValue()
  def stubInfo: StubInfo = _stubInfo

  private final var sequenceNumber: Int = 0
  private final var mock: AnyRef = null
  private final var method: MockitoMethod = null
  private final var arguments: Array[AnyRef] = null
  private final var rawArguments: Array[AnyRef] = null
  private final var location: Location = null
  private var verified: Boolean = false
  private var _isIgnoredForVerification: java.lang.Boolean = false
  private[invocation] final var realMethod: RealMethod = null
  private var _stubInfo: StubInfo = null
}

/**
 * Method call on a mock object.
 * 

* Contains sequence number which should be globally unique and is used for * verification in order. *

* Contains stack trace of invocation */ @SuppressWarnings(Array("unchecked")) object Invocation { def expandVarArgs(isVarArgs: Boolean, args: Array[AnyRef]): Array[AnyRef] = { if (!isVarArgs || args(args.length - 1) != null && !args(args.length - 1).getClass.isArray) { return if (args == null) new Array[AnyRef](0) else args } val nonVarArgsCount: Int = args.length - 1 var varArgs: Array[AnyRef] = null if (args(nonVarArgsCount) == null) varArgs = Array[AnyRef](null) else varArgs = ArrayEquals.createObjectArray(args(nonVarArgsCount)) val varArgsCount: Int = varArgs.length var newArgs: Array[AnyRef] = new Array[AnyRef](nonVarArgsCount + varArgsCount) System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount) System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount) newArgs } val serialVersionUID: Long = 8240069639250980199L val MAX_LINE_LENGTH: Int = 45 }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy