2016-10-15 2 views
2

전체 코드는 https://github.com/JJ/spray-test입니다. 상태를 공유하기 위해 전역 객체 (스칼라가 올바른 동작인지 여부는 알 수 없음)를 사용하고 있습니다. 스프레이 앱에서.전역 변수를 사용한 이상한 스칼라 테스트 동작 : 지연을 포함하여 성공합니다.

path(Segment) { quien => 
    get { 
     println(Apuestas) // also Thread.wait(100) 
     val esta_apuesta = Apuestas.get(quien) 
     complete(esta_apuesta) 
    } 
    } 

테스트 코드의 필수적인 부분이

"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") 
     } 
    } 

입니다

을 (https://github.com/JJ/spray-test/blob/master/src/main/scala/info/CC_MII/MyService.scala에 전체 파일을 확인하시기 바랍니다) : putget 따라서,지도에서 값을 가져,지도에 추가 문제는 코드의 첫 번째 덩어리에 있습니다. 내가 println 문을 주석 처리하면 작동하지 않고 실패합니다. 다음은 오류 메시지입니다. [error] 'There was an internal server error.' doesn't contain 'Alguien' (MyServiceSpec.scala:49) "get"부분이 아직 작동하지 않았거나 다른 스레드에 있다는 것을 분명하게 나타내거나 실제로 문제가 무엇인지 알지 못합니다.

그것은 아마 동기화와 somesuch와 관련이있다. 그리고 나는 아마 다른 방법으로 Apuestas를 가지고 있고 선언해야한다. 그러나 나는 이것에서 아주 새롭다. 그리고 나는 매우 행복하게 계몽 될 것이다.

나는 또한 해당 지역의 PR 홍보에 관심이있는 경우를 대비하여 hacktoberbest 라벨이있는 저장소의 문제로 포함했습니다. https://github.com/JJ/spray-test/issues

업데이트는 : 배우가 상태를 공유해서는 안, 즉, Unintended change to local variable of a Scala Actor하지만 그것을 시행 할 수있는 프로그램에 달려이이 질문에 관련이있을 것으로 보인다. 것은, 잘, 그들은 do 주를 그러나 우리가 인쇄하는 경우에한다. 어쩌면 스레드에 지연을 도입해도 동일한 효과가 있습니까? 나는 그것이 모든 나쁜 형태와 최악의 실천과 모든 나머지라는 것을 알고 있지만, 위에서 말했듯이, 나는 행복하게 그것을하는 올바른 방법으로 깨우칠 것입니다.

2 업데이트를 : 나는 이렇게 방법을 동기화 시도하지 않은 :

def add(apuesta: Apuesta): Apuesta = synchronized { 
    { 
     this.apuestas += (apuesta.quien -> apuesta) 
    } 
    apuesta 
    } 

을 여전히 주사위. 나는 여전히 Apuesta 객체 전체를 인쇄하거나 스레드에서 기다려야하므로 더 많은 문제가 발생합니다. 동기화를 통해 수행 할 수없는 println의 기능은 무엇입니까?

업데이트 3 : 잠시 동안 테스트 한 후 println은 시간의 일부만 "동기화"합니다. 아직도 무작위로 실패합니다. 어떻게 든 타이밍과 관계가 있지만 어떻게 볼 수는 없습니다.

+0

이것은 실제로 이상한 행동이 아니며, 동시성이 우리 인간에게 어떻게 보이는지를 보여줍니다. 동시 응용 프로그램의 흐름을 추적하는 데 어려움을 완화하기위한 도구 및 모델이 있지만 제약 조건을 준수하는 경우에만 작동합니다. 공유 상태가없는 것과 같은 제약 조건. 시작하기 좋은 점 : https://www.packtpub.com/application-development/learning-concurrent-programming-scala – michaJlS

+0

모든 것을 다시 작성하기에는 부족합니다. ? – jjmerelo

답변

2

테스트간에 종속성이 있으므로 실패합니다. Get("/Alguien") 요청을하기 전에 Put("/0/2/Alguien")을 완료해야합니다. 그렇지 않으면 info.CC_MII.Apuestas#apuestasalguien 키가없는 항목이 있으며 액세스하려고하면 응용 프로그램이 실패합니다.

print의 형태로 지연을 도입했거나 Thread.wait(100)을 직접 사용하여 지연을 도입하여 Put 요청을 완료했습니다. 인쇄물이나 수면을 서비스에 넣는 대신에 어쨌든 GET의 테스트 실행을 지연 시키면 조금 더 좋을 것입니다.

다른 옵션 (더 나은)은 apuestas 맵의 초기 값 인 info.CC_MII.Apuestas에 상태를 주입 할 수 있습니다. 그런 다음 테스트를 설정하는 동안 몇 가지 항목을 제공하고 Get 요청으로 Alguien 대신 가져 오기를 시도 할 수 있습니다.

+0

그건 문제가 아닌 것 같습니다. 첫째, 테스트 측에서 호출이 완료되거나 이전 테스트가 실패합니다. 프로그램 방식이 아닌 다른 방식으로 전화를 거는 방법은 없습니다. 둘째, 서버 측에서 Thread.wait은 몇 가지 문제를 일으 킵니다. 즉, 테스트가 바로 수행되면 호출을 중단합니다. 게다가 내가 언급 한 println에 대한 재미있는 점은 변수를 포함시키는 것이 _ 필요하다는 것인데, 그렇지 않으면 작동하지 않을 것이다. 인쇄는 약간의 변수 매직에 익숙하지 않다 ... Thread.wait은 테스트에서 작동하지 않는다. – jjmerelo