Integration-Test of Future 结果导致通过明显错误的测试
Integration-Test of Future results leads to passing tests that are obviously wrong
考虑以下测试:
class BookTest extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfter
{
implicit val defaultPatience =
PatienceConfig(timeout = Span(5, Seconds), interval = Span(500, Millis))
val db = Database.forURL("jdbc:sqlite:/home/myhome/test.sqlite", driver = "org.sqlite.JDBC")
private val books = Books.all
val setup = DBIO.seq(
// Create the tables, including primary and foreign keys
(books.schema).create,
// Insert some dummy data
books += new Book(-1, 0, "Awesome Title #1"),
books += new Book(-1, 1, "Gorgeous successor"),
books += new Book(-1, 2, "Nasty prequel")
)
db.run(setup)
"Books" should "be a Sequences of Books" in
{
val bookList = db.run(books.result)
whenReady(bookList)
{
result => result shouldBe a [Seq[Int]]
}
}
"Books" should "contain the books we inserted" in
{
val bookList: Future[Seq[Book]] = db.run(books.result)
whenReady(bookList)
{
result =>
{
println("TYPE OF RESULT:" result)
result.length === 1334
// result(0).title === "Awesome Title #1"
}
}
}
我明确说明了 bookList
的类型,这是一个包裹在未来的书籍序列。
现在我预计 result shouldBe a [Seq[Int]]
会失败,因为 Seq[Int] != Seq[Book]
第二个测试也returns正确,但是为什么呢?结果的长度应该是3...总是通过。
我哪里想错了? whenReady(bookList)
与 defaultPatience 和 Future 的结合是否能达到我期望的效果?
编辑: 只是为了说明这一点,数据库已创建并已填充,因此可以正常工作(已通过 sqlite3
验证;))
编辑: 我是如何解决这两个问题的:
1)
"Books" should "be a Sequences of Books" in
{
val bookList: Future[Seq[Book]] = db.run(books.result)
whenReady(bookList)
{
result => {
result shouldBe a [Seq[_]] // Remember type erasure
result(0) shouldBe a [Book]
}
}
}
2)(这真的很蠢,但是你..)
"Books" should "contain the books we inserted" in
{
val bookList = db.run(books.result)
whenReady(bookList)
{
result =>
{
result.length shouldBe 3
result(0).title shouldBe "Awesome Title #1"
}
}
}
你被JVM type erasure. From ScalaTest Using matchers击中:
Because type parameters are erased on the JVM, we recommend you insert an underscore for any type parameters when using this syntax. Both of the following test only that the result is an instance of List[_], because at runtime the type parameter has been erased:
result shouldBe a [List[_]] // recommended
result shouldBe a [List[Fruit]] // discouraged
第二个测试没有should和assert,只是一个fruitlessresult.length === 1334
。如Checking equality with matchers所述:
result.length should === (1334)
或
result.length shouldBe 1334
考虑以下测试:
class BookTest extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfter
{
implicit val defaultPatience =
PatienceConfig(timeout = Span(5, Seconds), interval = Span(500, Millis))
val db = Database.forURL("jdbc:sqlite:/home/myhome/test.sqlite", driver = "org.sqlite.JDBC")
private val books = Books.all
val setup = DBIO.seq(
// Create the tables, including primary and foreign keys
(books.schema).create,
// Insert some dummy data
books += new Book(-1, 0, "Awesome Title #1"),
books += new Book(-1, 1, "Gorgeous successor"),
books += new Book(-1, 2, "Nasty prequel")
)
db.run(setup)
"Books" should "be a Sequences of Books" in
{
val bookList = db.run(books.result)
whenReady(bookList)
{
result => result shouldBe a [Seq[Int]]
}
}
"Books" should "contain the books we inserted" in
{
val bookList: Future[Seq[Book]] = db.run(books.result)
whenReady(bookList)
{
result =>
{
println("TYPE OF RESULT:" result)
result.length === 1334
// result(0).title === "Awesome Title #1"
}
}
}
我明确说明了 bookList
的类型,这是一个包裹在未来的书籍序列。
现在我预计 result shouldBe a [Seq[Int]]
会失败,因为 Seq[Int] != Seq[Book]
第二个测试也returns正确,但是为什么呢?结果的长度应该是3...总是通过。
我哪里想错了? whenReady(bookList)
与 defaultPatience 和 Future 的结合是否能达到我期望的效果?
编辑: 只是为了说明这一点,数据库已创建并已填充,因此可以正常工作(已通过 sqlite3
验证;))
编辑: 我是如何解决这两个问题的:
1)
"Books" should "be a Sequences of Books" in
{
val bookList: Future[Seq[Book]] = db.run(books.result)
whenReady(bookList)
{
result => {
result shouldBe a [Seq[_]] // Remember type erasure
result(0) shouldBe a [Book]
}
}
}
2)(这真的很蠢,但是你..)
"Books" should "contain the books we inserted" in
{
val bookList = db.run(books.result)
whenReady(bookList)
{
result =>
{
result.length shouldBe 3
result(0).title shouldBe "Awesome Title #1"
}
}
}
你被JVM type erasure. From ScalaTest Using matchers击中:
Because type parameters are erased on the JVM, we recommend you insert an underscore for any type parameters when using this syntax. Both of the following test only that the result is an instance of List[_], because at runtime the type parameter has been erased:
result shouldBe a [List[_]] // recommended result shouldBe a [List[Fruit]] // discouraged
第二个测试没有should和assert,只是一个fruitlessresult.length === 1334
。如Checking equality with matchers所述:
result.length should === (1334)
或
result.length shouldBe 1334