-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move matchers from cats into common, add smart constructors (#260) [c…
…i skip] * Smart constructor for EqTo that returns ArgumentMatcher. A subtype won't get picked up by the cats syntax machinery. * Move matchers from cats into common and add tests.
- Loading branch information
1 parent
50bad8b
commit febdec6
Showing
11 changed files
with
165 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package org.mockito | ||
package matchers | ||
|
||
/** Combine multiple matchers using AND | ||
*/ | ||
case class AllOf[A] private (matchers: List[ArgumentMatcher[A]]) extends ArgumentMatcher[A] { | ||
override def matches(a: A) = matchers.forall(_.matches(a)) | ||
|
||
override def toString = | ||
matchers match { | ||
case Nil => "<any>" | ||
case matcher :: Nil => matcher.toString | ||
case _ => matchers.mkString("allOf(", ", ", ")") | ||
} | ||
} | ||
|
||
object AllOf { | ||
def apply[A](matchers: ArgumentMatcher[A]*): ArgumentMatcher[A] = | ||
new AllOf(matchers.flatMap { | ||
case AllOf(ms) => ms | ||
case m => List(m) | ||
}.toList) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
common/src/main/scala/org/mockito/matchers/ProductOf.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.mockito | ||
package matchers | ||
|
||
/** The product (2-tuple) of two matchers | ||
*/ | ||
case class ProductOf[A, B] private (ma: ArgumentMatcher[A], mb: ArgumentMatcher[B]) extends ArgumentMatcher[(A, B)] { | ||
override def matches(ab: (A, B)) = ab match { case (a, b) => ma.matches(a) && mb.matches(b) } | ||
override def toString = s"productOf($ma, $mb)" | ||
} | ||
|
||
object ProductOf { | ||
def apply[A, B](ma: ArgumentMatcher[A], mb: ArgumentMatcher[B]): ArgumentMatcher[(A, B)] = | ||
new ProductOf(ma, mb) | ||
} |
16 changes: 16 additions & 0 deletions
16
common/src/main/scala/org/mockito/matchers/Transformed.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.mockito | ||
package matchers | ||
|
||
/** Matcher tranformed from one type to another with a function to modify the input | ||
* | ||
* Technically this is 'contramapped' but that seemed like an unnecessarily jargony name. | ||
*/ | ||
case class Transformed[A, B] private (ma: ArgumentMatcher[A])(f: B => A) extends ArgumentMatcher[B] { | ||
override def matches(b: B) = ma.matches(f(b)) | ||
override def toString = s"transformed($ma: $f)" | ||
} | ||
|
||
object Transformed { | ||
def apply[A, B](ma: ArgumentMatcher[A])(f: B => A): ArgumentMatcher[B] = | ||
new Transformed(ma)(f) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.mockito | ||
|
||
package object matchers { | ||
private val AnyArgMatcher: ArgumentMatcher[Any] = AllOf[Any]() | ||
|
||
def AnyArg[A]: ArgumentMatcher[A] = AnyArgMatcher.asInstanceOf[ArgumentMatcher[A]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.mockito | ||
package matchers | ||
|
||
import org.scalacheck.Arbitrary | ||
|
||
object Generators { | ||
implicit def arbArgumentMatcher[A](implicit a: Arbitrary[A => Boolean]): Arbitrary[ArgumentMatcher[A]] = | ||
Arbitrary(a.arbitrary.map(p => new ArgumentMatcher[A] { def matches(a: A) = p(a) })) | ||
} |
60 changes: 60 additions & 0 deletions
60
common/src/test/scala/org/mockito/matchers/MatcherProps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package org.mockito | ||
package matchers | ||
|
||
import cats.laws.discipline.MiniInt | ||
import cats.laws.discipline.arbitrary._ | ||
import org.mockito.internal.matchers._ | ||
import org.scalacheck._ | ||
|
||
import Arbitrary.arbitrary | ||
import Gen._ | ||
import Prop._ | ||
|
||
class MatcherProps extends Properties("matchers") { | ||
import Generators._ | ||
|
||
property("AllOf") = forAll(chooseNum(0, 8))(length => | ||
forAll(listOfN(length, arbitrary[ArgumentMatcher[MiniInt]]), arbitrary[MiniInt]) { | ||
case (matchers, value) => | ||
val allOf = AllOf(matchers: _*) | ||
val stringRep = allOf.toString | ||
|
||
classify(allOf.matches(value), "matches", "doesn't match") { | ||
(allOf.matches(value) ?= matchers.forall(_.matches(value))) :| "matches all underlying" && | ||
matchers.iff { | ||
case Nil => stringRep ?= "<any>" | ||
case matcher :: Nil => stringRep ?= matcher.toString() | ||
case _ => stringRep ?= s"allOf(${matchers.mkString(", ")})" | ||
} :| "renders to string correctly" | ||
|
||
} | ||
} | ||
) | ||
|
||
property("ProductOf") = forAll { (ma: ArgumentMatcher[MiniInt], mb: ArgumentMatcher[String], a: MiniInt, b: String) => | ||
val productOf = ProductOf(ma, mb) | ||
val product = (a, b) | ||
|
||
val maMatches = ma.matches(a) | ||
val mbMatches = mb.matches(b) | ||
val productMatches = productOf.matches(product) | ||
|
||
classify(productMatches, "matches", "doesn't match") { | ||
all( | ||
(productMatches ==> maMatches) :| "ma matches if product does", | ||
(productMatches ==> mbMatches) :| "mb matches if product does", | ||
((maMatches && mbMatches) ==> productMatches) :| "product matches if both ma and mb do", | ||
(productOf.toString ?= s"productOf($ma, $mb)") :| "renders to string correctly" | ||
) | ||
} | ||
} | ||
|
||
property("Transformed") = forAll { (ma: ArgumentMatcher[String], f: MiniInt => String, value: MiniInt) => | ||
val transformed = Transformed(ma)(f) | ||
val matches = transformed.matches(value) | ||
classify(matches, "matches", "doesn't match") { | ||
(matches ?= ma.matches(f(value))) :| "matches if underlying matches transfomed value" && | ||
(transformed.toString ?= s"transformed($ma: $f)") :| "renders to string correctly" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters