2015-06-28 3 views
0

Я написал этот гладкий DAO и его модульный тест в specs2.Состояние гонки в Slick Code

Мой код имеет расу условия. Когда я запускаю те же тесты, я получаю разные результаты.

The гонки условия существуют, хотя в обеих функциях я Await.result (будущее, Duration.Inf)

DAO

package com.example 
import slick.backend.DatabasePublisher 
import slick.driver.H2Driver.api._ 

import scala.concurrent.ExecutionContext.Implicits.global 
import slick.jdbc.meta._ 
import scala.concurrent._ 
import ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 

case class Person(id: Int, firstname: String, lastname: String) 

class People(tag: Tag) extends Table[Person](tag, "PEOPLE") { 
    def id = column[Int]("PERSON_ID", O.PrimaryKey) 
    def firstname = column[String]("PERSON_FIRST_NAME") 
    def lastname = column[String]("PERSON_LAST_NAME") 
    def * = (id, firstname, lastname) <> (Person.tupled, Person.unapply _) 
} 

object PersonDAO { 

    private def createList(numRows: Int) : List[Person] = { 
    def recFunc(counter: Int, result: List[Person]) : List[Person] = { 
     counter match { 
     case x if x <= numRows => recFunc(counter + 1, Person(counter, "test" + counter, "user" + counter) :: result) 
     case _ => result 
     } 
    } 
    recFunc(1, List[Person]()) 
    } 

    val db = Database.forConfig("test1") 
    val people = TableQuery[People] 

    def createAndPopulate(numRows: Int) = { 
    val action1 = people.schema.create 
    val action2 = people ++= Seq(createList(numRows) : _*) 
    val combined = db.run(action1 andThen action2) 

    val future1 = combined.map { result => 
     result map {x => 
     println(s"number of rows inserted $x") 
     x 
     } 
    } 
    Await.result(future1, Duration.Inf).getOrElse(0) 
    } 

    def printAll() = { 
    val a = people.result 
    val b = db.run(a) 
    val y = b map { result => 
     result map {x => x} 
    } 
    val z = Await.result(y, Duration.Inf) 
    println(z) 
    println(z.length) 
    z 
    } 
} 

Unit Test

import org.specs2.mutable._ 
import com.example._ 

class HelloSpec extends Specification { 
    "This usecase " should { 
    "should insert rows " in { 
     val x = PersonDAO.createAndPopulate(100) 
     x === 100 
    } 
    } 

    "This usecase " should { 
    "return 100 rows" in { 
     val x = PersonDAO.printAll() 
     val y = PersonDAO.printAll()  
     y.length === 100 
    } 
    } 
} 

Когда я бегу этот же код с использованием activator test Я вижу 2 разных типа выходов на разных трассах

  1. иногда код получает за исключением

    количество строк, вставленных 100 [Информация] HelloSpec [Информация] [Информация] Этот UseCase следует [Информация] + должен вставить строки [информация] [информация ] Эта информация должна быть [info]! return 100 rows [ошибка] JdbcSQLException:: Таблица PEOPLE не найдена; SQL: [ошибка] выберите x2. «PERSON_ID», x2. «PERSON_FIRST_NAME», x2. «PERSON_LAST_NAME» из «PEOPLE» x2 [42S02-60] (Message.java:84) [error] org.h2. message.Message.getSQLException (Message.java:84) [ошибка] org.h2.message.Message.getSQLException (Message.java:88) [ошибка] org.h2.message.Message.getSQLException (Message.java: 66)

  2. Иногда вызов первой функции возвращает 0 строк и вызов второй функции возвращает 100 значений

    SLF4J: Не удалось загрузить класс «org.slf4j.impl.StaticLoggerBinder». SLF4J: Реализация регистратора без операции (NOP) SLF4J: См. http://www.slf4j.org/codes.html#StaticLoggerBinder для получения дополнительной информации. Число вставленных строк 100 Vector() Вектор (100, test100, user100), Person (99, test99, user99), Person (98, test98, user98), Person (97, test97, user97) , Person (96, test96, user96), Person (95, test95, user95), Person (94, test94, user94), Person (93, test93, user93), Person (92, test92, user92), Person (91, test91, user91), лицо (90, test90, user90), лицо (89, test89, user89), лицо (88, test88, user88), лицо (87, test87, user87), Person

I не понимаю, почему мой код имеет эти условия гонки, потому что я блокирую будущее в каждом методе.

ответ

1

Ваше предположение, что два тестовых примера должны запускаться серийно, один за другим неправильный. Тестирование выполняется параллельно. Просто используйте sequential, чтобы убедиться в этом.

Смежные вопросы