Using a HavePropertyMatcher for collection elements in ScalaTest?
I've been using ScalaTest's FeatureSpec for a couple of days now and I'm trying to understand if it's possible to define the following spec using the built-in matchers (and if not, how I can write a suitable custom matcher).
Suppose I have the class Book:
case class Book(val title: String, val author: String)
and in my test I have a List of books:
val books = List(Book("Moby Dick", "Melville"))
Now, I would like to specify that the books list should contain a book with the title "Moby Dick". I would like to write something like:
books should contain (value with title "Moby Dick")
I can't seem to figure out from the docs and code if it's possible to express this requirement in ScalaTest. Has anyone ran 开发者_Python百科into a similar situation?
In the meantime here's a custom matcher you can use:
def containElement[T](right: Matcher[T]) = new Matcher[Seq[T]] {
def apply(left: Seq[T]) = {
val matchResults = left map right
MatchResult(
matchResults.find(_.matches) != None,
matchResults.map(_.failureMessage).mkString(" and "),
matchResults.map(_.negatedFailureMessage).mkString(" and ")
)
}
}
Then you can use the full power of the ScalaTest Have
matcher to inspect the fields of your object:
val books = List(Book("Moby Dick", "Melville"),
Book("Billy Budd", "Melville"),
Book("War and Peace", "Tolstoy"))
books should containElement(have('title("Moby Dick")))
books should containElement(have('title("Billy Budd"), 'author("Melville")))
books should containElement(have('title("War and Peace"), 'author("Melville")))
The last one is a failure producing this output:
The title property had value "Moby Dick", instead of its expected value "War and Peace", on object Book(Moby Dick,Melville) and The title property had value "Billy Budd", instead of its expected value "War and Peace", on object Book(Billy Budd,Melville) and The author property had value "Tolstoy", instead of its expected value "Melville", on object Book(War and Peace,Tolstoy)
You can also combine matchers with and
or or
, use not
, etc.
Not currently, though you will be able to do something like this very soon in the future. What you can do now is something like:
books.exists(_.title == "Moby Dick") should be (true)
精彩评论