Marek Jeszka Marek Jeszka - 3 months ago 9
Scala Question

Close or shutdown of H2 database after tests is not working

I am facing a problem of database clean-up after each test when using scalatest with Slick.

Here is code of the test:

class H2DatabaseSpec extends WordSpec with Matchers with ScalaFutures with BeforeAndAfter {
implicit override val patienceConfig = PatienceConfig(timeout = Span(5, Seconds))

val h2DB: H2DatabaseService = new H2DatabaseService
var db: Database = _

before {
db = Database.forConfig("h2mem1")
h2DB.createSchema.futureValue
}

after {
db.shutdown.futureValue
}

"H2 database" should {
"query a question" in {
val newQuestion: QuestionEntity = QuestionEntity(Some(1L), "First question")
h2DB.insertQuestion(newQuestion).futureValue

val question = h2DB.getQuestionById(1L)

question.futureValue.get shouldBe newQuestion
}
}

it should {
"query all questions" in {
val newQuestion: QuestionEntity = QuestionEntity(Some(2L), "Second question")
h2DB.insertQuestion(newQuestion).futureValue

val questions = h2DB.getQuestions

questions.futureValue.size shouldBe 1
}
}
}


Database service is just invoking
run
method on defined database:

class H2DatabaseService {

val db = Database.forConfig("h2mem1")

val questions = TableQuery[Question]

def createSchema =
db.run(questions.schema.create)

def getQuestionById(id: Long): Future[Option[QuestionEntity]] =
db.run(questions.filter(_.id === id).result.headOption)

def getQuestions: Future[Seq[QuestionEntity]] =
db.run(questions.result)

def insertQuestion(question: QuestionEntity): Future[Int] =
db.run(questions += question)
}

class Question(tag: Tag) extends Table[QuestionEntity](tag, "QUESTION") {
def id = column[Option[Long]]("QUESTION_ID", O.PrimaryKey, O.AutoInc)
def title = column[String]("TITLE")

def * = (id, title) <> ((QuestionEntity.apply _).tupled, QuestionEntity.unapply)
}

case class QuestionEntity(id: Option[Long] = None, title: String) {
require(!title.isEmpty, "title.empty")
}


And the database is defined as follows:

h2mem1 = {
url = "jdbc:h2:mem:test1"
driver = org.h2.Driver
connectionPool = disabled
keepAliveConnection = true
}


I am using Scala 2.11.8, Slick 3.1.1, H2 database 1.4.192 and scalatest 2.2.6.

Error that appears when tests are executed is
Table "QUESTION" already exists
. So it looks like
shutdown()
method has no effect at all (but it is invoked - checked in debugger).

Anybody knows how to handle such scenario? How to clean-up database properly after each test?

Answer

Database has not been correctly cleaned-up because of invoking the method on different object.

H2DatabaseService has it's own db object and the test it's own. Issue was fixed after refactoring H2 database service and invoking:

after {
  h2DB.db.shutdown.futureValue
}