2017-09-20 7 views
0

私はGETおよびPOST要求を行うためにAkka HTTPクライアントを作成しています。ドキュメントからFutureベースの例を使用しています。 「ローカル変数インスタンスを見つけることができません」というエラーが表示されます。簡単なコードとテストケースがあります。コードは何GET要求のためのakka-httpクライアントは、ローカル変数インスタンスを見つけることができません。

package com.epl.akka 
import akka.actor.{Actor, ActorLogging, ActorSystem, Props} 
import akka.http.scaladsl.Http 
import akka.http.scaladsl.model.{HttpMethods, HttpRequest, HttpResponse, StatusCodes} 
import akka.stream.{ActorMaterializer, ActorMaterializerSettings} 
import akka.util.ByteString 
import com.epl.akka.AkkaHTTPClient.GET 

class AkkaHTTPClient() extends Actor 
    with ActorLogging { 

    import akka.pattern.pipe 
    import context.dispatcher 

    final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) 

    val http = Http(context.system) 

    override def receive: Receive = { 
    case GET(uri: String) => 
     log.info("getting the url") 
     http 
     .singleRequest(HttpRequest(HttpMethods.GET,uri = uri)) 
     .pipeTo(self) 

    case HttpResponse(StatusCodes.OK, headers, entity, _) => 
     entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body => 
     log.info("Got response, body: " + body.utf8String) 
     } 

    case resp @ HttpResponse(code, _, _, _) => 
     log.info("Request failed, response code: " + code) 
     resp.discardEntityBytes() 
    } 
} 

object AkkaHTTPClient { 

    def props() = 
    Props[AkkaHTTPClient] 

    final case class GET(uri: String){} 
} 

はURLをクロールして、JSONの結果を作成するために、JSoupによって解析されるHTML応答を返しています。

テストケース:

class AkkaHTTPClientSpec(_system: ActorSystem) 
    extends TestKit(_system) 
    with Matchers 
    with FlatSpecLike 
    with BeforeAndAfterAll { 

    def this() = this(ActorSystem("AkkaHTTPClientSpec")) 

    override def afterAll: Unit = { 
    shutdown(system) 
    } 

    "A AkkaHttpClient Actor" should "give HTML response when instructed to" in { 
    val testProbe = TestProbe() 

    val url = "http://www.premierleague.com" 
    val akkaHTTPClientActor = system.actorOf(AkkaHTTPClient.props(),"AkkaHttpClient") 
    akkaHTTPClientActor ! GET(url) 
    } 
} 

コードがval http = Http(context.system)を呼び出した後に失敗しました。どんな助けもありがとうございます。

+0

あなたは完全を投稿することができますが、エラーメッセージ「ローカル変数のインスタンスを見つけることができませんか」? –

答えて

0

私はあなたのコードを次のようにマイナーな変更を加え、そしてアッカHTTP 10.0.10とScalaの2.12で渡さテスト:http://www.premierleague.comにGETリクエストをすることになったので

  1. は、http://akka.ioにURLを変更301ステータスコード。
  2. 元の送信者に「OK応答」メッセージを送信するようにクライアントコードを変更しました。
  3. ImplicitSenderの特性が混在しており、テストを変更してクライアントからの「OK応答」メッセージを期待していました。

私がより有意義なテストをするために行った後者の2つの変更。

以下は正常に実行される調整コードです。まず、クライアント:

package com.epl.akka 

import akka.actor._ 
import akka.http.scaladsl.Http 
import akka.http.scaladsl.model._ 
import akka.stream.{ActorMaterializer, ActorMaterializerSettings} 
import akka.util.ByteString 

import com.epl.akka.AkkaHTTPClient.GET 

class AkkaHTTPClient() extends Actor with ActorLogging { 
    import akka.pattern.pipe 
    import context.dispatcher 

    final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system)) 

    val http = Http(context.system) 

    var originalSender: Option[ActorRef] = None // <-- added 

    override def receive: Receive = { 
    case GET(uri: String) => 
     val s = sender    // <-- added 
     originalSender = Option(s) // <-- added 
     log.info("getting the url") 
     http 
     .singleRequest(HttpRequest(HttpMethods.GET,uri = uri)) 
     .pipeTo(self) 

    case HttpResponse(StatusCodes.OK, headers, entity, _) => 
     entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body => 
     log.info("Got response, body: " + body.utf8String) 
     } 
     originalSender.foreach(_ ! "OK response") // <-- added 

    case resp @ HttpResponse(code, _, _, _) => 
     log.info("Request failed, response code: " + code) 
     resp.discardEntityBytes() 
    } 
} 

object AkkaHTTPClient { 
    def props() = Props[AkkaHTTPClient] 
    final case class GET(uri: String) 
} 

そしてスペック:

package com.epl.akka 

import akka.actor.{Actor, ActorSystem} 
import akka.testkit.{ImplicitSender, TestKit} 

import com.epl.akka.AkkaHTTPClient.GET 
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers} 

import scala.concurrent.duration._ 

class AkkaHTTPClientSpec(_system: ActorSystem) 
    extends TestKit(_system) 
    with ImplicitSender // <-- added 
    with Matchers 
    with FlatSpecLike 
    with BeforeAndAfterAll { 

    def this() = this(ActorSystem("AkkaHTTPClientSpec")) 

    override def afterAll: Unit = { 
    shutdown(system) 
    } 

    "An AkkaHTTPClient Actor" should "give HTML response when instructed to" in { 
    val url = "http://akka.io" // <-- changed 
    val akkaHTTPClientActor = system.actorOf(AkkaHTTPClient.props(), "AkkaHttpClient") 
    akkaHTTPClientActor ! GET(url) 
    expectMsg(20.seconds, "OK response") // <-- added 
    } 
} 
+0

ここで送信者が必要な理由を説明してください。私が持っていたコードはakkaの文書からの正確なコピーでした – SanjeevGhimire

+0

@SanjeevGhimire:私が答えで述べたように、送信者をキャプチャすることは単にテスト目的のためです。 – chunjef

+0

しかし、テスト目的で使用される送信者がなければ、コードは機能しません。 – SanjeevGhimire

関連する問題