在 ScalaTest 中对集合元素使用 HavePropertyMatcher?

发布于 2024-11-28 19:51:48 字数 479 浏览 1 评论 0原文

我已经使用 ScalaTest 的 FeatureSpec 有几天了,我试图了解是否可以使用内置匹配器定义以下规范(如果不能,我如何编写合适的自定义匹配器)。

假设我有 Book: 类,

case class Book(val title: String, val author: String)

并且在我的测试中我有一个书籍列表:

val books = List(Book("Moby Dick", "Melville"))

现在,我想指定书籍列表应包含一本标题为“Moby Dick”的书。我想写这样的内容:

books should contain (value with title "Moby Dick")  

我似乎无法从文档和代码中弄清楚是否可以在 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 into a similar situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

隐诗 2024-12-05 19:51:48

同时,您可以使用以下自定义匹配器:

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 ")
    )
  }
}

然后您可以使用 ScalaTest Have 匹配器的全部功能来检查对象的字段:

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")))

最后一个是产生以下输出的失败:

在对象 Book(Moby Dick,Melville) 上,标题属性的值为“Moby Dick”,而不是其预期值“战争与和平”,并且标题属性的值为“Billy Budd”,而不是其预期值“战争与和平”,在对象 Book(Billy Budd,Melville) 上,作者属性的值为“Tolstoy”,而不是其预期值“Melville”,在对象 Book(War and Peace,Tolstoy) 上

您还可以将匹配器与andor,使用 not 等。

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.

尴尬癌患者 2024-12-05 19:51:48

目前还不行,尽管您将来很快就可以做这样的事情。你现在可以做的是:

books.exists(_.title == "Moby Dick") should be (true)

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)
溺孤伤于心 2024-12-05 19:51:48

有一个专门构建的 scalatest 类,名为 LoneElement

https://www.scalatest.org/scaladoc/3.0.8/org/scalatest/LoneElement.html

import org.scalatest.LoneElement.convertToCollectionLoneElementWrapper

books.loneElement.title shouldBe "Moby Dick"

There is a purposely built scalatest class called LoneElement:

https://www.scalatest.org/scaladoc/3.0.8/org/scalatest/LoneElement.html

import org.scalatest.LoneElement.convertToCollectionLoneElementWrapper

books.loneElement.title shouldBe "Moby Dick"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文