2016-10-15 2 views
2

まず、コード全体がhttps://github.com/JJ/spray-test です。状態を共有するためにグローバルオブジェクト(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") 
     } 
    } 

です:putgetは、このように、マップから値を取得し、地図に追加されます問題は、コードの最初のチャンクにあります。私がprintlnステートメントをコメントアウトすると、それは動作せず、失敗します。これはエラーメッセージです: [error] 'There was an internal server error.' doesn't contain 'Alguien' (MyServiceSpec.scala:49) "get"パートがまだ動作していないか、別のスレッドに入っていることを示しているか、何が問題なのか本当にわかりません。

これは多分同期化と関連していることでしょう。私はおそらくApuestasを別の方法で持っていなければなりませんが、私はこれでかなり新しくて、とてもうれしく悟ります。

私はまた、ラベル付きのレポの問題として、この分野で1つのPRを進めることに興味がある場合に備えて、これを問題に含めました。 https://github.com/JJ/spray-test/issues

更新:、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は時間の一部を「同期」します。まだランダムに失敗します。それは何とかタイミングと関係があるが、どうやって見えるのか分からない。

+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

それは問題ではないようです。まず、テスト側では、呼び出しが完了するか、以前のテストが失敗しました。プログラム単位以外の呼び出しを順序付ける方法はありません。第2に、サーバ側では、Thread.waitはいくつかの問題を引き起こします。テストが直後に行われると、単に呼び出しを中止します。私が言及したprintlnに関する面白いことは、変数をインクルードする必要があるか、それともうまくいかないということです。私は慣れていないいくつかの可変的なマジックをキックします... Thread.waitはテストでも動作しません。 – jjmerelo

関連する問題