Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import sbt.Keys._

import scala.io.Source
import scala.language.postfixOps
import scala.util.Try
Expand Down Expand Up @@ -78,6 +76,17 @@ lazy val publishSettings = Seq(
)
)

lazy val noPublishingSettings = Seq(
publish := {},
publishLocal := {},
publishArtifact := false,
)

lazy val noCrossBuildSettings = Seq(
crossScalaVersions := Nil,
publish / skip := true
)

lazy val scalatest = (project in file("scalatest"))
.dependsOn(core)
.dependsOn(common % "compile-internal, test-internal")
Expand Down Expand Up @@ -134,14 +143,12 @@ lazy val common = (project in file("common"))
.dependsOn(macroCommon)
.settings(
commonSettings,
noPublishingSettings,
libraryDependencies ++= Dependencies.commonLibraries ++ Seq(
Dependencies.scalaReflection(scalaVersion.value),
Dependencies.catsLaws % "test",
Dependencies.scalacheck % "test"
),
publish := {},
publishLocal := {},
publishArtifact := false
)
)

lazy val core = (project in file("core"))
Expand Down Expand Up @@ -185,6 +192,7 @@ lazy val macroSub = (project in file("macro"))
.dependsOn(common)
.settings(
commonSettings,
noPublishingSettings,
libraryDependencies ++= Dependencies.commonLibraries,
libraryDependencies += Dependencies.scalaReflection(scalaVersion.value),
publish := {},
Expand All @@ -195,14 +203,13 @@ lazy val macroSub = (project in file("macro"))
lazy val macroCommon = (project in file("macro-common"))
.settings(
commonSettings,
noPublishingSettings,
libraryDependencies += Dependencies.scalaReflection(scalaVersion.value),
publish := {},
publishLocal := {},
publishArtifact := false
)

lazy val root = (project in file("."))
.settings(
publish := {},
publishLocal := {}
) aggregate (common, core, scalatest, specs2, cats, scalaz)
.settings(noPublishingSettings, noCrossBuildSettings)
.aggregate (common, core, scalatest, specs2, cats, scalaz)
30 changes: 25 additions & 5 deletions macro/src/main/scala/org/mockito/captor/Captor.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.mockito.captor

import org.mockito.internal.MacroDebug.debugResult
import org.mockito.exceptions.verification.ArgumentsAreDifferent
import org.mockito.exceptions.verification.{ ArgumentsAreDifferent, TooFewActualInvocations, TooManyActualInvocations }
import org.mockito.{ clazz, ArgumentCaptor }
import org.scalactic.Equality
import org.scalactic.TripleEquals._

import scala.collection.JavaConverters._
import scala.reflect.ClassTag
import scala.reflect.macros.blackbox
import scala.util.{ Failure, Try }

import org.mockito.exceptions.base.MockitoAssertionError

trait Captor[T] {
def capture: T
Expand All @@ -17,10 +19,28 @@ trait Captor[T] {

def values: List[T]

def hasCaptured(expectations: T*)(implicit $eq: Equality[T]): Unit =
expectations.zip(values).foreach { case (e, v) =>
if (e !== v) throw new ArgumentsAreDifferent(s"Got [$v] instead of [$e]")
def hasCaptured(expectations: T*)(implicit $eq: Equality[T]): Unit = {
val elementResult = Try {
expectations.zip(values).foreach { case (e, v) =>
if (e !== v) throw new ArgumentsAreDifferent(s"Got [$v] instead of [$e]")
}
}

val sizeResult = Try {
(expectations.size, values.size) match {
case (es, vs) if es - vs > 0 => throw new TooFewActualInvocations(s"Also expected ${es - vs} more: [${expectations.drop(vs).mkString(", ")}]")
case (es, vs) if es - vs < 0 => throw new TooManyActualInvocations(s"Also got ${vs - es} more: [${values.drop(es).mkString(", ")}]")
case _ => None
}
}

(elementResult, sizeResult) match {
case (Failure(ef), Failure(sf: MockitoAssertionError)) => throw new MockitoAssertionError(sf, ef.getMessage)
case (_, Failure(sf)) => throw sf
case (Failure(ef), _) => throw ef
case _ =>
}
}
}

class WrapperCaptor[T: ClassTag] extends Captor[T] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package user.org.mockito.captor

import org.mockito.captor.{ ArgCaptor, ValCaptor }
import org.mockito.captor.ArgCaptor
import org.mockito.exceptions.base.MockitoAssertionError
import org.mockito.exceptions.verification.{ TooFewActualInvocations, TooManyActualInvocations }
import org.mockito.{ IdiomaticMockito, MockitoSugar }
import org.scalactic.{ Equality, StringNormalizations }
import user.org.mockito.captor.ArgCaptorTest._
Expand Down Expand Up @@ -100,6 +102,81 @@ class ArgCaptorTest extends AnyWordSpec with MockitoSugar with Matchers {
captor.hasCaptured("it worked!", "it worked again!")
}

"report failure" when {

"fewer values were captured than expected" in {
val aMock = mock[Foo]
val captor = ArgCaptor[String]

aMock.stringArgument("it worked!")
aMock.stringArgument("it worked again!")

verify(aMock, times(2)).stringArgument(captor)

captor.values.should(contain).only("it worked!", "it worked again!")

the[TooManyActualInvocations] thrownBy {
captor.hasCaptured("it worked!")
} should have message "Also got 1 more: [it worked again!]"
}

"more values were captured than expected" in {
val aMock = mock[Foo]
val captor = ArgCaptor[String]

aMock.stringArgument("it worked!")

verify(aMock, times(1)).stringArgument(captor)

captor.values.should(contain).only("it worked!")

the[TooFewActualInvocations] thrownBy {
captor.hasCaptured("it worked!", "it worked again!")
} should have message "Also expected 1 more: [it worked again!]"
}

"fewer values were captured than expected while wrong values were captured" in {
val aMock = mock[Foo]
val captor = ArgCaptor[String]

aMock.stringArgument("it worked again!")

verify(aMock, times(1)).stringArgument(captor)

captor.values.should(contain).only("it worked again!")

val error = the[MockitoAssertionError] thrownBy {
captor.hasCaptured("it worked!", "it worked again!")
}

error.getMessage should (
include("Got [it worked again!] instead of [it worked!]") and
include("Also expected 1 more: [it worked again!]")
)
}

"more values were captured than expected while wrong values were captured" in {
val aMock = mock[Foo]
val captor = ArgCaptor[String]

aMock.stringArgument("it worked!")
aMock.stringArgument("it worked again!")

verify(aMock, times(2)).stringArgument(captor)

captor.values.should(contain).only("it worked!", "it worked again!")

val error = the[MockitoAssertionError] thrownBy {
captor.hasCaptured("it worked again!")
}

error.getMessage should (
include("Got [it worked!] instead of [it worked again!]") and
include("Also got 1 more: [it worked again!]")
)
}
}

"work with value case classes" in {
val aMock = mock[Foo]
val captor = ArgCaptor[Name]
Expand Down