在每个测试函数

时间:2016-03-01 16:53:44

标签: scala playframework

我正在编写与数据库交互的测试,并且希望进行某种特定于每个测试的设置和拆卸。这就是我目前所拥有的:

"my test" in {

    // Use anorm to populate the database
    Db.withConnection { 

        SQL"INSERT INTO ...".execute()

        // Do some tests
        foo must equal 1
        bar must equal 2

        // Remove the test data
        SQL"DELETE FROM ...".execute()
    }
}

这种方法的问题在于,如果其中一个测试失败,那么执行将暂停,测试数据永远不会从数据库中删除。

2 个答案:

答案 0 :(得分:0)

假设您正在使用specs2,您可以为每个测试创建Around范围:

"my test" in DatabaseSetup {
  // Do some tests
  foo must equal 1
  bar must equal 2
}

trait DatabaseSetup extends org.specs2.mutable.Around {
  def around[T: org.specs2.execute.AsResult](t: => T) = {

    Db.withConnection {
      // Insert data
    }

    val result = org.specs2.execute.AsResult(t)

    Db.withConnection {
      // Remove data
    }

    result
  }
}

无论如何,这可能很难维护,这样的结构可能会显示您的生产代码或测试代码的某些问题。你应该问问自己为什么不能重用数据库设置。

答案 1 :(得分:0)

如果您正在使用specs2进行测试,那么@ marcospereira的答案很有效,但我使用的是PlaySpec。以下示例:

  1. 在数据库中插入行
  2. 设置rowID,以便可以在其他任何地方使用
  3. 向服务器发出GET请求,该请求取决于rowID
  4. 测试结果,
  5. 从数据库中删除相应的行。

    import anorm._
    import org.scalatest.{BeforeAndAfter, DoNotDiscover}
    import org.scalatestplus.play.{ConfiguredServer, PlaySpec}
    import play.api.db.DB
    import play.api.libs.json.Json
    import play.api.libs.ws.WS
    import play.api.test.Helpers._
    
    @DoNotDiscover
    class ExampleSpec extends PlaySpec with BeforeAndAfter with ConfiguredServer {
    
        val baseAddress =  s"http://localhost:$testServerPort/"
        var rowID: Int = _
    
        before {
            DB.withConnection { implicit connection =>
                rowID = SQL"INSERT INTO some_table (col1, col2) VALUES('v1', 'v2')".executeInsert(SqlParser.scalar[Int].single)
            }
        }
    
        after {
            DB.withConnection { implicit connection =>
                SQL"DELETE FROM some_table WHERE id = $rowID".execute()
            }
        }
    
        "GET my/endpoint/{id}" should {
    
            "return a 200" in {
                val address = baseAddress + s"my/endpoint/$rowID"
    
                val response = await(WS.url(address).get())
                response.status mustEqual OK
            }
        }
    }