Во-первых, весь код находится в https://github.com/JJ/spray-test Я использую глобальный объект (который я не знаю, является ли это правильным поведением Scala) для совместного использования состояния в приложении Spray. put
добавляет к карте, get
получает значения из карты, таким образом:Weird Scala поведение теста с глобальными переменными: в том числе задержка делает его успешным
path(Segment) { quien =>
get {
println(Apuestas) // also Thread.wait(100)
val esta_apuesta = Apuestas.get(quien)
complete(esta_apuesta)
}
}
(пожалуйста, проверьте весь файл https://github.com/JJ/spray-test/blob/master/src/main/scala/info/CC_MII/MyService.scala)
Основные части тестового кода
"Crea apuestas correctamente" in {
Put("/0/2/Alguien") ~> myRoute ~> check {
response.entity should not be equalTo(None)
responseAs[String] must contain("Alguien")
}
Put("/3/0/Menda") ~> myRoute ~> check {
response.entity should not be equalTo(None)
responseAs[String] must contain("Menda")
}
}
"GET recupera apuesta correctamente" in {
Get("/Alguien") ~> myRoute ~> check {
response.entity should not be equalTo(None)
responseAs[String] must contain("Alguien")
}
}
Проблема заключается в первом фрагменте кода. Если я прокомментирую заявление println
, он не работает, и он терпит неудачу. Это сообщение об ошибке: [error] 'There was an internal server error.' doesn't contain 'Alguien' (MyServiceSpec.scala:49)
Что очевидно указывает на то, что часть «получить» еще не работает, или она находится в другом потоке, или я действительно не знаю, что случилось.
Возможно, это связано с синхронизацией, и я должен, вероятно, иметь и объявить Apuestas каким-то другим способом, но я совершенно новый в этом, и я очень счастливо просвещен.
Я также включил это как проблему в репо с лейблом hacktoberbest
, на случай, если кто-то заинтересован в продвижении одного PR в этой области. https://github.com/JJ/spray-test/issues
Update: Это, кажется, связано с этим вопросом: Unintended change to local variable of a Scala Actor, то есть субъекты не должны разделять государства, но это до программы для обеспечения соблюдения его. Дело в том, что они делают делить состояние, но только если мы печатаем. Возможно, введение задержки в поток имеет такой же эффект? Я знаю, что это плохая форма, худшая практика и все остальное, но, как сказано выше, я бы с радостью просветил правильный способ сделать это.
второе обновление: Я пытался синхронизировать методы таким образом:
def add(apuesta: Apuesta): Apuesta = synchronized {
{
this.apuestas += (apuesta.quien -> apuesta)
}
apuesta
}
Еще нет костей. Я все равно должен либо распечатать весь объект Apuesta, либо ждать в потоке, что вызывает больше проблем. Что делает println сделать это через синхронизацию?
Обновление 3: После тестирования какое-то время println только «синхронизирует» часть времени. Все еще происходит случайным образом. Это как-то связано с таймингом, но не может понять, как это сделать.
Это не странное поведение, это просто способ, которым параллелизм выглядит для нас человеком. Существуют некоторые инструменты и модели, которые предназначены для устранения трудностей с отслеживанием потока параллельного приложения, но они работают только в том случае, если вы подчиняетесь их ограничениям. Такие ограничения, как отсутствие общего состояния и т. Д. Хороший момент для запуска: https://www.packtpub.com/application-development/learning-concurrent-programming-scala – michaJlS
Итак, чтобы не переписывать все, что-то, что можно сделать по этому поводу ? – jjmerelo