2015-08-31 2 views
20

Так у меня есть функция с этой подписью (akka.http.model.HttpResponse):Akka HttpResponse чтения тела, как Струнный Скале

def apply(query: Seq[(String, String)], accept: String): HttpResponse 

Я просто получить значение в тесте, как:

val resp = TagAPI(Seq.empty[(String, String)], api.acceptHeader) 

Я хочу, чтобы проверить свое тело в тест что-то вроде:

resp.entity.asString == "tags" 

Мой вопрос, как я могу получить тело ответа в виде строки?

+0

Соответствующие: http://stackoverflow.com/q/31532838/390708 – Brian

+2

Вы используете 'Акку-HTTP-testkit'? Если да, вы можете использовать 'entityAs [String]' в тесте, чтобы получить тело как значение String. – jrudolph

+0

Мне нужно использовать PlaySpec, поэтому я не могу использовать akka-http-testkit :( – tg44

ответ

16

Поскольку Akka Http основан на потоках, объект также работает. Если вам действительно нужна целая строка сразу, вы можете конвертировать входящий запрос в Strict:

Это делается с помощью API toStrict(timeout: FiniteDuration)(mat: Materializer) для сбора запроса в строгую сущность в течение заданного срока (это важно так как вы не хотите, чтобы «попытаться собрать объект навсегда» в случае, если входящий запрос не на самом деле никогда не заканчивается):

import akka.stream.ActorFlowMaterializer 
import akka.actor.ActorSystem 

implicit val system = ActorSystem("Sys") // your actor system, only 1 per app 
implicit val materializer = ActorFlowMaterializer() // you must provide a materializer 

import system.dispatcher 
import scala.concurrent.duration._ 
val timeout = 300.millis 

val bs: Future[ByteString] = entity.toStrict(timeout).map { _.data } 
val s: Future[String] = bs.map(_.utf8String) // if you indeed need a `String` 
+0

Кажется, это хороший способ, но какой неявный FlowMaterializer вы используете? (Вы получаете его от импорта или используете некоторую реализацию по умолчанию?) – tg44

+0

Вы можете просто создать один ad hoc или повторно использовать существующий экземпляр, я изменил свой ответ. –

15
import akka.http.scaladsl.unmarshalling.Unmarshal 


    implicit val system = ActorSystem("System") 
    implicit val materializer = ActorFlowMaterializer() 

    val responseAsString: Future[String] = Unmarshal(entity).to[String] 
+0

Какую версию akka-http-core вы используете для этого? С 2.4.6 я не нахожу 'akka.http. scaladsl.unmarshalling', где угодно. – akauppi

+1

@akauppi это 'akka-http-experimental' не' akka-http-core' – wlk

1

к сожалению, в моем случае, Unmarshal в строку не работает должным образом жалуясь на: Unsupported Content-Type, supported: application/json. Это было бы более элегантное решение, но мне пришлось использовать другой способ. В моем тесте я использовал будущее, извлеченные из объекта ответа и ОЖИДАНИЯ (от scala.concurrent), чтобы получить результат из будущего:

Put("/post/item", requestEntity) ~> route ~> check { 
     val responseContent: Future[Option[String]] = 
     response.entity.dataBytes.map(_.utf8String).runWith(Sink.lastOption) 

     val content: Option[String] = Await.result(responseContent, 10.seconds) 
     content.get should be(errorMessage) 
     response.status should be(StatusCodes.InternalServerError) 
    } 

Если вам нужно пройти через все линии в ответ, вы можете использовать runForeach Источник:

response.entity.dataBytes.map(_.utf8String).runForeach(data => println(data)) 
1

Вы также можете попробовать этот вариант.

responseObject.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String) map println 
Смежные вопросы