package matchers
Classes and traits for matchers.
This package is released as part of the scalatest-matchers-core
module.
- Source
- package.scala
- Alphabetic
- By Inheritance
- matchers
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Package Members
- package dsl
Classes and traits supporting ScalaTest's matchers DSL.
Classes and traits supporting ScalaTest's matchers DSL.
This package is released as part of the
scalatest-matchers-core
module. - package must
- package should
Trait and object for ScalaTest Matchers DSL using
should
.Trait and object for ScalaTest Matchers DSL using
should
.This package is released as part of the
scalatest-shouldmatchers
module.
Type Members
- trait BeMatcher[-T] extends (T) => MatchResult
Trait extended by matcher objects, which may appear after the word
be
, that can match a value of the specified type.Trait extended by matcher objects, which may appear after the word
be
, that can match a value of the specified type. The value to match is passed to theBeMatcher
'sapply
method. The result is aMatchResult
. ABeMatcher
is, therefore, a function from the specified type,T
, to aMatchResult
.Although
BeMatcher
andMatcher
represent very similar concepts, they have no inheritance relationship becauseMatcher
is intended for use right aftershould
ormust
whereasBeMatcher
is intended for use right afterbe
.As an example, you could create
BeMatcher[Int]
calledodd
that would match any oddInt
, and one calledeven
that would match any evenInt
. Given this pair ofBeMatcher
s, you could check whether anInt
was odd or even with expressions like:num should be (odd) num should not be (even)
Here's is how you might define the odd and even
BeMatchers
:trait CustomMatchers {
class OddMatcher extends BeMatcher[Int] { def apply(left: Int) = MatchResult( left % 2 == 1, left.toString + " was even", left.toString + " was odd" ) } val odd = new OddMatcher val even = not (odd) }
// Make them easy to import with: // import CustomMatchers._ object CustomMatchers extends CustomMatchersThese
BeMatcher
s are defined inside a trait to make them easy to mix into any suite or spec that needs them. TheCustomMatchers
companion object exists to make it easy to bring theBeMatcher
s defined in this trait into scope via importing, instead of mixing in the trait. The ability to import them is useful, for example, when you want to use the matchers defined in a trait in the Scala interpreter console.Here's an rather contrived example of how you might use
odd
andeven
:class DoubleYourPleasureSuite extends FunSuite with MustMatchers with CustomMatchers {
def doubleYourPleasure(i: Int): Int = i * 2
test("The doubleYourPleasure method must return proper odd or even values")
val evenNum = 2 evenNum must be (even) doubleYourPleasure(evenNum) must be (even)
val oddNum = 3 oddNum must be (odd) doubleYourPleasure(oddNum) must be (odd) // This will fail } }The last assertion in the above test will fail with this failure message:
6 was even
For more information on
MatchResult
and the meaning of its fields, please see the documentation forMatchResult
. To understand whyBeMatcher
is contravariant in its type parameter, see the section entitled "Matcher's variance" in the documentation forMatcher
. - final case class BePropertyMatchResult(matches: Boolean, propertyName: String) extends Product with Serializable
The result of a
Boolean
property match operation, such as one performed by aBePropertyMatcher
, which contains one field that indicates whether the match succeeded (i.e., theBoolean
property wastrue
) and one field that provides the name of the property.The result of a
Boolean
property match operation, such as one performed by aBePropertyMatcher
, which contains one field that indicates whether the match succeeded (i.e., theBoolean
property wastrue
) and one field that provides the name of the property.For an example of a
BePropertyMatchResult
in action, see the documentation forBePropertyMatcher
.- matches
indicates whether or not the matcher matched (if the
Boolean
property was true, it was a match)- propertyName
the name of the
Boolean
property that was matched against
- trait BePropertyMatcher[-T] extends (T) => BePropertyMatchResult
Trait extended by matcher objects, which may appear after the word
be
, that can match against aBoolean
property.Trait extended by matcher objects, which may appear after the word
be
, that can match against aBoolean
property. The match will succeed if and only if theBoolean
property equalstrue
. The object containing the property, which must be of the type specified by theBePropertyMatcher
's type parameterT
, is passed to theBePropertyMatcher
'sapply
method. The result is aBePropertyMatchResult
. ABePropertyMatcher
is, therefore, a function from the specified type,T
, to aBePropertyMatchResult
.Although
BePropertyMatcher
andMatcher
represent similar concepts, they have no inheritance relationship becauseMatcher
is intended for use right aftershould
ormust
whereasBePropertyMatcher
is intended for use right afterbe
.A
BePropertyMatcher
essentially allows you to write statically typedBoolean
property assertions similar to the dynamic ones that use symbols:tempFile should be a ('file) // dynamic: uses reflection tempFile should be a (file) // type safe: only works on Files; no reflection used
One good way to organize custom matchers is to place them inside one or more traits that you can then mix into the suites or specs that need them. Here's an example that includes two
BePropertyMatcher
s:trait CustomMatchers {
class FileBePropertyMatcher extends BePropertyMatcher[java.io.File] { def apply(left: java.io.File) = BePropertyMatchResult(left.isFile, "file") }
class DirectoryBePropertyMatcher extends BePropertyMatcher[java.io.File] { def apply(left: java.io.File) = BePropertyMatchResult(left.isDirectory, "directory") }
val file = new FileBePropertyMatcher val directory = new DirectoryBePropertyMatcher }Because the type parameter of these two
BePropertyMatcher
s isjava.io.File
, they can only be used with instances of that type. (The compiler will enforce this.) All they do is create aBePropertyMatchResult
whosematches
field istrue
if and only if theBoolean
property istrue
. The second field,propertyName
, is simply the string name of the property. Thefile
anddirectory
val
s create variables that can be used in matcher expressions that test whether ajava.io.File
is a file or a directory. Here's an example:class ExampleSpec extends RefSpec with Matchers with CustomMatchers {
describe("A temp file") {
it("should be a file, not a directory") {
val tempFile = java.io.File.createTempFile("delete", "me")
try { tempFile should be a (file) tempFile should not be a (directory) } finally { tempFile.delete() } } } }These matches should succeed, but if for example the first match,
tempFile should be a (file)
, were to fail, you would get an error message like:/tmp/delme1234me was not a file
For more information on
BePropertyMatchResult
and the meaning of its fields, please see the documentation forBePropertyMatchResult
. To understand whyBePropertyMatcher
is contravariant in its type parameter, see the section entitled "Matcher's variance" in the documentation forMatcher
. - final case class HavePropertyMatchResult[P](matches: Boolean, propertyName: String, expectedValue: P, actualValue: P) extends Product with Serializable
The result of a property match operation such as one performed by a
HavePropertyMatcher
, which contains one field that indicates whether the match succeeded (i.e., the property had its expected value), one field that provides the name of the property, and two fields giving the expected and actual values.The result of a property match operation such as one performed by a
HavePropertyMatcher
, which contains one field that indicates whether the match succeeded (i.e., the property had its expected value), one field that provides the name of the property, and two fields giving the expected and actual values.HavePropertyMatchResult
's type parameter,P
, specifies the type of the property.For an example of a
HavePropertyMatchResult
in action, see the documentation forHavePropertyMatcher
.- matches
indicates whether or not the matcher matched (if the property had its expected value, it was a match)
- propertyName
the name of the property (of type
P
) that was matched against- expectedValue
the expected value of the property
- actualValue
the actual value of the property
- trait HavePropertyMatcher[-T, P] extends (T) => HavePropertyMatchResult[P]
Trait extended by matcher objects, which may appear after the word
have
, that can match against a property of the type specified by theHavePropertyMatcher
's second type parameterP
.Trait extended by matcher objects, which may appear after the word
have
, that can match against a property of the type specified by theHavePropertyMatcher
's second type parameterP
.HavePropertyMatcher
's first type parameter,T
, specifies the type that declares the property. The match will succeed if and only if the value of the property equals the specified value. The object containing the property is passed to theHavePropertyMatcher
'sapply
method. The result is aHavePropertyMatchResult[P]
. AHavePropertyMatcher
is, therefore, a function from the specified type,T
, to aHavePropertyMatchResult[P]
.Although
HavePropertyMatcher
andMatcher
represent similar concepts, they have no inheritance relationship becauseMatcher
is intended for use right aftershould
ormust
whereasHavePropertyMatcher
is intended for use right afterhave
.A
HavePropertyMatcher
essentially allows you to write statically typed property assertions similar to the dynamic ones that use symbols:book should have ('title ("Moby Dick")) // dynamic: uses reflection book should have (title ("Moby Dick")) // type safe: only works on Books; no reflection used
One good way to organize custom matchers is to place them inside one or more traits that you can then mix into the suites or specs that need them. Here's an example that includes two methods that produce
HavePropertyMatcher
s:case class Book(val title: String, val author: String)
trait CustomMatchers {
def title(expectedValue: String) = new HavePropertyMatcher[Book, String] { def apply(book: Book) = HavePropertyMatchResult( book.title == expectedValue, "title", expectedValue, book.title ) }
def author(expectedValue: String) = new HavePropertyMatcher[Book, String] { def apply(book: Book) = HavePropertyMatchResult( book.author == expectedValue, "author", expectedValue, book.author ) } }Each time the
title
method is called, it returns a newHavePropertyMatcher[Book, String]
that can be used to match against thetitle
property of theBook
passed to itsapply
method. Because the type parameter of these twoHavePropertyMatcher
s isBook
, they can only be used with instances of that type. (The compiler will enforce this.) The match will succeed if thetitle
property equals the value passed asexpectedValue
. If the match succeeds, thematches
field of the returnedHavePropertyMatchResult
will betrue
. The second field,propertyName
, is simply the string name of the property. The third and fourth fields,expectedValue
andactualValue
indicate the expected and actual values, respectively, for the property. Here's an example that uses theseHavePropertyMatchers
:class ExampleSpec extends RefSpec with Matchers with CustomMatchers {
describe("A book") {
it("should have the correct title and author") {
val book = Book("Moby Dick", "Melville")
book should have ( title ("Moby Dick"), author ("Melville") ) } } }These matches should succeed, but if for example the first property,
title ("Moby Dick")
, were to fail, you would get an error message like:The title property had value "A Tale of Two Cities", instead of its expected value "Moby Dick", on object Book(A Tale of Two Cities,Dickens)
For more information on
HavePropertyMatchResult
and the meaning of its fields, please see the documentation forHavePropertyMatchResult
. To understand whyHavePropertyMatcher
is contravariant in its type parameter, see the section entitled "Matcher's variance" in the documentation forMatcher
. - final case class LazyArg(arg: Any)(f: (Any) => String) extends Product with Serializable
Transforms a given object's
toString
with a given function lazily.Transforms a given object's
toString
with a given function lazily.This class is intended to be used with the
mapResult
method ofMatcherProducers
, which you can use to modify error messages when composing matchers. This class exists to enable those error messages to be modified lazily, so thattoString
is invoked on the givenarg
, and its result transformed by the given functionf
, only when and if thetoString
method is invoked on theLazyArg
. As a performance optimization, ScalaTest'sMatchResult
avoids invokingtoString
on objects until and unless an error message is actually needed, to minimize unecessary creation and concatenation of strings. TheLazyArg
class enables this same performance optimization when composing matchers.The other design goal of
LazyArg
is to make the internalarg
available for inspection in an IDE. In a future version of ScalaTest, theargs
ofMatchResult
that were used to create the error message will be included in theTestFailedException
, so they can be inspected in IDEs. This is why thearg
field ofLazyArg
is public.For an example of using
LazyArg
, see the Composing matchers section in the main documentation for traitMatcher
.- arg
the argument
- f
a function that given the
arg
will produce aString
- sealed case class MatchResult(matches: Boolean, rawFailureMessage: String, rawNegatedFailureMessage: String, rawMidSentenceFailureMessage: String, rawMidSentenceNegatedFailureMessage: String, failureMessageArgs: IndexedSeq[Any], negatedFailureMessageArgs: IndexedSeq[Any], midSentenceFailureMessageArgs: IndexedSeq[Any], midSentenceNegatedFailureMessageArgs: IndexedSeq[Any]) extends Product with Serializable
The result of a match operation, such as one performed by a
Matcher
orBeMatcher
, which contains one field that indicates whether the match succeeded, four fields that provide raw failure messages to report under different circumstances, four fields providing arguments used to construct the final failure messages using raw failure messages and aPrettifier
.The result of a match operation, such as one performed by a
Matcher
orBeMatcher
, which contains one field that indicates whether the match succeeded, four fields that provide raw failure messages to report under different circumstances, four fields providing arguments used to construct the final failure messages using raw failure messages and aPrettifier
. Using the default constructor, failure messages will be constructed lazily (when required).A
MatchResult
'smatches
field indicates whether a match succeeded. If it succeeded,matches
will betrue
. There are four methods,failureMessage
,negatedfailureMessage
,midSentenceFailureMessage
andnegatedMidSentenceFailureMessage
that can be called to get final failure message strings, one of which will be presented to the user in case of a match failure. If a match succeeds, none of these strings will be used, because no failure message will be reported (i.e., because there was no failure to report). If a match fails (matches
isfalse
), thefailureMessage
(ormidSentenceFailure
—more on that below) will be reported to help the user understand what went wrong.Understanding
negatedFailureMessage
The
negatedFailureMessage
exists so that it can become thefailureMessage
if the matcher is inverted, which happens, for instance, if it is passed tonot
. Here's an example:val equalSeven = equal (7) val notEqualSeven = not (equalSeven)
The
Matcher[Int]
that results from passing 7 toequal
, which is assigned to theequalSeven
variable, will compareInt
s passed to itsapply
method with 7. If 7 is passed, theequalSeven
match will succeed. If anything other than 7 is passed, it will fail. By contrast, thenotEqualSeven
matcher, which results from passingequalSeven
tonot
, does just the opposite. If 7 is passed, thenotEqualSeven
match will fail. If anything other than 7 is passed, it will succeed.For example, if 8 is passed,
equalSeven
'sMatchResult
will contain:expression: equalSeven(8) matches: false failureMessage: 8 did not equal 7 negatedFailureMessage: 8 equaled 7
Although the
negatedFailureMessage
is nonsensical, it will not be reported to the user. Only thefailureMessage
, which does actually explain what caused the failure, will be reported by the user. If you pass 8 tonotEqualSeven
'sapply
method, by contrast, thefailureMessage
andnegatedFailureMessage
will be:expression: notEqualSeven(8) matches: true failureMessage: 8 equaled 7 negatedFailureMessage: 8 did not equal 7
Note that the messages are swapped from the
equalSeven
messages. This swapping was effectively performed by thenot
matcher, which in addition to swapping thefailureMessage
andnegatedFailureMessage
, also inverted thematches
value. Thus when you pass the same value to bothequalSeven
andnotEqualSeven
thematches
field of oneMatchResult
will betrue
and the otherfalse
. Because thematches
field of theMatchResult
returned bynotEqualSeven(8)
istrue
, the nonsensicalfailureMessage
, "8 equaled 7
", will not be reported to the user.If 7 is passed, by contrast, the
failureMessage
andnegatedFailureMessage
ofequalSeven
will be:expression: equalSeven(7) matches: true failureMessage: 7 did not equal 7 negatedFailureMessage: 7 equaled 7
In this case
equalSeven
'sfailureMessage
is nonsensical, but because the match succeeded, the nonsensical message will not be reported to the user. If you pass 7 tonotEqualSeven
'sapply
method, you'll get:expression: notEqualSeven(7) matches: false failureMessage: 7 equaled 7 negatedFailureMessage: 7 did not equal 7
Again the messages are swapped from the
equalSeven
messages, but this time, thefailureMessage
makes sense and explains what went wrong: thenotEqualSeven
match failed because the number passed did in fact equal 7. Since the match failed, this failure message, "7 equaled 7
", will be reported to the user.Understanding the "
midSentence
" messagesWhen a ScalaTest matcher expression that involves
and
oror
fails, the failure message that results is composed from the failure messages of the left and right matcher operatnds toand
or or. For example:8 should (equal (7) or equal (9))
This above expression would fail with the following failure message reported to the user:
8 did not equal 7, and 8 did not equal 9
This works fine, but what if the failure messages being combined begin with a capital letter, such as:
The name property did not equal "Ricky"
A combination of two such failure messages might result in an abomination of English punctuation, such as:
The name property did not equal "Ricky", and The name property did not equal "Bobby"
Because ScalaTest is an internationalized application, taking all of its strings from a property file enabling it to be localized, it isn't a good idea to force the first character to lower case. Besides, it might actually represent a String value which should stay upper case. The
midSentenceFailureMessage
exists for this situation. If the failure message is used at the beginning of the sentence,failureMessage
will be used. But if it appears mid-sentence, or at the end of the sentence,midSentenceFailureMessage
will be used. Given these failure message strings:failureMessage: The name property did not equal "Bobby" midSentenceFailureMessage: the name property did not equal "Bobby"
The resulting failure of the
or
expression involving to matchers would make any English teacher proud:The name property did not equal "Ricky", and the name property did not equal "Bobby"
- matches
indicates whether or not the matcher matched
- rawFailureMessage
raw failure message to report if a match fails
- rawNegatedFailureMessage
raw message with a meaning opposite to that of the failure message
- rawMidSentenceFailureMessage
raw failure message suitable for appearing mid-sentence
- rawMidSentenceNegatedFailureMessage
raw negated failure message suitable for appearing mid-sentence
- failureMessageArgs
arguments for constructing failure message to report if a match fails
- negatedFailureMessageArgs
arguments for constructing message with a meaning opposite to that of the failure message
- midSentenceFailureMessageArgs
arguments for constructing failure message suitable for appearing mid-sentence
- midSentenceNegatedFailureMessageArgs
arguments for constructing negated failure message suitable for appearing mid-sentence
- trait Matcher[-T] extends (T) => MatchResult
Trait extended by objects that can match a value of the specified type.
Trait extended by objects that can match a value of the specified type. The value to match is passed to the matcher's
apply
method. The result is aMatchResult
. A matcher is, therefore, a function from the specified type,T
, to aMatchResult
.Creating custom matchers
If none of the built-in matcher syntax satisfies a particular need you have, you can create custom
Matcher
s that allow you to place your own syntax directly aftershould
. For example, although you can ensure that ajava.io.File
has a name that ends with a particular extension like this:file.getName should endWith (".txt")
You might prefer to create a custom
Matcher[java.io.File]
namedendWithExtension
, so you could write expressions like:file should endWithExtension ("txt") file should not endWithExtension "txt" file should (exist and endWithExtension ("txt"))
One good way to organize custom matchers is to place them inside one or more traits that you can then mix into the suites that need them. Here's an example:
import org.scalatest._ import matchers._
trait CustomMatchers {
class FileEndsWithExtensionMatcher(expectedExtension: String) extends Matcher[java.io.File] {
def apply(left: java.io.File) = { val name = left.getName MatchResult( name.endsWith(expectedExtension), s"""File $name did not end with extension "$expectedExtension"""", s"""File $name ended with extension "$expectedExtension"""" ) } }
def endWithExtension(expectedExtension: String) = new FileEndsWithExtensionMatcher(expectedExtension) }
// Make them easy to import with: // import CustomMatchers._ object CustomMatchers extends CustomMatchersNote: the
CustomMatchers
companion object exists to make it easy to bring the matchers defined in this trait into scope via importing, instead of mixing in the trait. The ability to import them is useful, for example, when you want to use the matchers defined in a trait in the Scala interpreter console.This trait contains one matcher class,
FileEndsWithExtensionMatcher
, and adef
namedendWithExtension
that returns a new instance ofFileEndsWithExtensionMatcher
. Because the class extendsMatcher[java.io.File]
, the compiler will only allow it be used to match against instances ofjava.io.File
. A matcher must declare anapply
method that takes the type decared inMatcher
's type parameter, in this casejava.io.File
. The apply method will return aMatchResult
whosematches
field will indicate whether the match succeeded. ThefailureMessage
field will provide a programmer-friendly error message indicating, in the event of a match failure, what caused the match to fail.The
FileEndsWithExtensionMatcher
matcher in this example determines success by determining if the passedjava.io.File
ends with the desired extension. It does this in the first argument passed to theMatchResult
factory method:name.endsWith(expectedExtension)
In other words, if the file name has the expected extension, this matcher matches. The next argument to
MatchResult
's factory method produces the failure message string:s"""File $name did not end with extension "$expectedExtension"""",
For example, consider this matcher expression:
import org.scalatest._ import Matchers._ import java.io.File import CustomMatchers._
new File("essay.text") should endWithExtension ("txt")Because the passed
java.io.File
has the nameessay.text
, but the expected extension is"txt"
, the failure message would be:File essay.text did not have extension "txt"
For more information on the fields in a
MatchResult
, including the subsequent field (or fields) that follow the failure message, please see the documentation forMatchResult
.Creating dynamic matchers
There are other ways to create new matchers besides defining one as shown above. For example, you might check that a file is hidden like this:
new File("secret.txt") should be ('hidden)
If you wanted to get rid of the tick mark, you could simply define
hidden
like this:val hidden = 'hidden
Now you can check that an file is hidden without the tick mark:
new File("secret.txt") should be (hidden)
You could get rid of the parens with by using
shouldBe
:new File("secret.txt") shouldBe hidden
Creating matchers using logical operators
You can also use ScalaTest matchers' logical operators to combine existing matchers into new ones, like this:
val beWithinTolerance = be >= 0 and be <= 10
Now you could check that a number is within the tolerance (in this case, between 0 and 10, inclusive), like this:
num should beWithinTolerance
When defining a full blown matcher, one shorthand is to use one of the factory methods in
Matcher
's companion object. For example, instead of writing this:val beOdd = new Matcher[Int] { def apply(left: Int) = MatchResult( left % 2 == 1, left + " was not odd", left + " was odd" ) }
You could alternately write this:
val beOdd = Matcher { (left: Int) => MatchResult( left % 2 == 1, left + " was not odd", left + " was odd" ) }
Either way you define the
beOdd
matcher, you could use it like this:3 should beOdd 4 should not (beOdd)
Composing matchers
You can also compose matchers. For example, the
endWithExtension
matcher from the example above can be more easily created by composing a function with the existingendWith
matcher:scala> import org.scalatest._ import org.scalatest._ scala> import Matchers._ import Matchers._ scala> import java.io.File import java.io.File scala> def endWithExtension(ext: String) = endWith(ext) compose { (f: File) => f.getPath } endWithExtension: (ext: String)org.scalatest.matchers.Matcher[java.io.File]
Now you have a
Matcher[File]
whoseapply
method first invokes the converter function to convert the passedFile
to aString
, then passes the resultingString
toendWith
. Thus, you could use this versionendWithExtension
like the previous one:scala> new File("output.txt") should endWithExtension("txt")
In addition, by composing twice, you can modify the type of both sides of a match statement with the same function, like this:
scala> val f = be > (_: Int) f: Int => org.scalatest.matchers.Matcher[Int] = <function1> scala> val g = (_: String).toInt g: String => Int = <function1> scala> val beAsIntsGreaterThan = (f compose g) andThen (_ compose g) beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1> scala> "8" should beAsIntsGreaterThan ("7")
At thsi point, however, the error message for the
beAsIntsGreaterThan
gives no hint that theInt
s being compared were parsed fromString
s:scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: 7 was not greater than 8
To modify error message, you can use trait
MatcherProducers
, which also provides acomposeTwice
method that performs thecompose
...andThen
...compose
operation:scala> import matchers._ import matchers._ scala> import MatcherProducers._ import MatcherProducers._ scala> val beAsIntsGreaterThan = f composeTwice g // means: (f compose g) andThen (_ compose g) beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1> scala> "8" should beAsIntsGreaterThan ("7")
Of course, the error messages is still the same:
scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: 7 was not greater than 8
To modify the error messages, you can use
mapResult
fromMatcherProducers
. Here's an example:scala> val beAsIntsGreaterThan = f composeTwice g mapResult { mr => mr.copy( failureMessageArgs = mr.failureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), negatedFailureMessageArgs = mr.negatedFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), midSentenceFailureMessageArgs = mr.midSentenceFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})), midSentenceNegatedFailureMessageArgs = mr.midSentenceNegatedFailureMessageArgs.map((LazyArg(_) { "\"" + _.toString + "\".toInt"})) ) } beAsIntsGreaterThan: String => org.scalatest.matchers.Matcher[String] = <function1>
The
mapResult
method takes a function that accepts aMatchResult
and produces a newMatchResult
, which can contain modified arguments and modified error messages. In this example, the error messages are being modified by wrapping the old arguments inLazyArg
instances that lazily apply the given prettification functions to thetoString
result of the old args. Now the error message is clearer:scala> "7" should beAsIntsGreaterThan ("8") org.scalatest.exceptions.TestFailedException: "7".toInt was not greater than "8".toInt
Matcher's variance
Matcher
is contravariant in its type parameter,T
, to make its use more flexible. As an example, consider the hierarchy:class Fruit class Orange extends Fruit class ValenciaOrange extends Orange
Given an orange:
val orange = Orange
The expression "
orange should
" will, via an implicit conversion inMatchers
, result in an object that has ashould
method that takes aMatcher[Orange]
. If the static type of the matcher being passed toshould
isMatcher[Valencia]
it shouldn't (and won't) compile. The reason it shouldn't compile is that the left value is anOrange
, but not necessarily aValencia
, and aMatcher[Valencia]
only knows how to match against aValencia
. The reason it won't compile is given thatMatcher
is contravariant in its type parameter,T
, aMatcher[Valencia]
is not a subtype ofMatcher[Orange]
.By contrast, if the static type of the matcher being passed to
should
isMatcher[Fruit]
, it should (and will) compile. The reason it should compile is that given the left value is anOrange
, it is also aFruit
, and aMatcher[Fruit]
knows how to match againstFruit
s. The reason it will compile is that given thatMatcher
is contravariant in its type parameter,T
, aMatcher[Fruit]
is indeed a subtype ofMatcher[Orange]
. - trait MatcherProducers extends AnyRef
Provides an implicit conversion on functions that produce
Matcher
s, i.e.,T => Matcher[T]
that enables you to modify error messages when composingMatcher
s.Provides an implicit conversion on functions that produce
Matcher
s, i.e.,T => Matcher[T]
that enables you to modify error messages when composingMatcher
s.For an example of using
MatcherProducers
, see the Composing matchers section in the main documentation for traitMatcher
.
Value Members
- object BeMatcher
Companion object for trait
BeMatcher
that provides a factory method that creates aBeMatcher[T]
from a passed function of type(T => MatchResult)
. - object BePropertyMatchResult extends Serializable
Companion object for the
BePropertyMatchResult
case class. - object BePropertyMatcher
Companion object for trait
BePropertyMatcher
that provides a factory method that creates aBePropertyMatcher[T]
from a passed function of type(T => BePropertyMatchResult)
. - object HavePropertyMatchResult extends Serializable
Companion object for the
HavePropertyMatchResult
case class. - object HavePropertyMatcher
Companion object for trait
HavePropertyMatcher
that provides a factory method that creates aHavePropertyMatcher[T]
from a passed function of type(T => HavePropertyMatchResult)
. - object MatchFailed
Singleton object that provides
unapply
method to extract failure message fromMatchResult
havingmatches
property value offalse
. - object MatchPatternHelper
MatchPatternHelper
is called byMatchPatternMacro
to supportmatchPattern
syntax. - object MatchResult extends Serializable
Companion object for the
MatchResult
case class. - object MatchSucceeded
Singleton object that provides
unapply
method to extract negated failure message fromMatchResult
havingmatches
property value oftrue
. - object Matcher
Companion object for trait
Matcher
that provides a factory method that creates aMatcher[T]
from a passed function of type(T => MatchResult)
. - object MatcherProducers extends MatcherProducers
Companion object that facilitates the importing of
MatcherProducers
members as an alternative to mixing it in.Companion object that facilitates the importing of
MatcherProducers
members as an alternative to mixing it in. One use case is to importMatcherProducers
's members so you can useMatcherProducers
in the Scala interpreter. - object TypeMatcherHelper
TypeMatcherHelper
is called byTypeMatcherMacro
to supporta [Type]
andan [Type]
syntax.TypeMatcherHelper
is called byTypeMatcherMacro
to supporta [Type]
andan [Type]
syntax.This object needs to be public so that the macro-generated code can be compiled. It is expected that ScalaTest users would ever need to use
TypeMatcherHelper
directly.