我正在使用Spray API,使用Akka路由器將傳入消息發送到處理邏輯的actor池。現在我想爲API編寫一些測試,但我正在努力爲代碼找到正確的結構。該API看起來此刻如下:使用Akka路由器測試Spray API
import akka.actor.{ActorRef, ActorSystem, Props, Actor}
import akka.io.IO
import akka.routing.SmallestMailboxPool
import akka.util.Timeout
import akka.pattern.ask
import com.typesafe.config.ConfigFactory
import spray.json._
import spray.can.Http
import scala.concurrent.duration._
import spray.routing._
import spray.http._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Success
import scala.util.Failure
object implicits{
implicit val system = ActorSystem("ApiSystem")
implicit val timeout = Timeout(5.seconds)
implicit val conf = ConfigFactory.load()
// Custom case class for parsing JSON parameter.
case class Msg(key1:String, key2:String, key3:Int)
object JsonProtocol extends DefaultJsonProtocol {
implicit val msg = jsonFormat3(Msg)
}
case class PostMsg(msg:String)
case object PostSuccess
case class PostFailure(msg:String)
}
import implicits._
object MyApi extends App {
override def main(Args: Array[String]):Unit = {
// create and start our service actor
val service = system.actorOf(Props(new MyApiActor(system)), "MyApi-service")
IO(Http) ? Http.Bind(service, interface = conf.getString("http.host"), port = conf.getInt("http.port"))
}
}
class MyApiActor(system: ActorSystem) extends Actor with MyApiService {
// the HttpService trait defines only one abstract member, which
// connects the services environment to the enclosing actor or test
def actorRefFactory = context
// this actor only runs our route, but you could add
// other things here, like request stream processing
// or timeout handling
def receive = runRoute(myRoute)
}
// this trait defines our service behavior independently from the service actor
trait MyApiService extends HttpService {
import implicits.JsonProtocol._
var actorPool = system.actorOf(SmallestMailboxPool(conf.getInt("actor-number")).props(Props(new HandlingActor(conf))), "msgRouter")
val myRoute =
path("msg") {
post {
entity(as[String]) { obj =>
try{
// if this parsing succeeds, the posted msg satisfies the preconditions set.
obj.parseJson.convertTo[Msg]
} catch {
case e: DeserializationException => {
complete(HttpResponse(status=StatusCodes.BadRequest, entity="Invalid json provided."))
}
case e: Exception => {
complete(HttpResponse(status=StatusCodes.InternalServerError, entity="Unknown internal server error."))
}
}
onComplete(actorPool ? PostMsg(obj)) {
case Success(value) => complete(HttpResponse(status = StatusCodes.OK, entity = "Pushed Msg"))
case Failure(value) => complete(HttpResponse(status = StatusCodes.InternalServerError, entity = "Handling failed."))
}
}
}
}
}
我想考的是API各種HTTP消息(即正確的電話,不正確的電話等)的響應。處理參與者的邏輯僅僅是將消息推送到Kafka總線,所以我想「嘲笑」這種行爲(即,如果此推送成功並能夠在推送失敗時測試API響應)。
我現在最掙扎的事情是如何設置測試。現在,我使用與所示主要方法中相同的命令來設置API,但我需要指定不同的actorPool,因爲我不希望任何消息被實際推送。我應該如何最好地去實現這樣的測試?
我正在使用Scalatest,使用Akka和Spray測試工具包。 (加上可能爲的Mockito如果必要的話嘲諷)
噴霧測試套件可讓您直接測試您的路線,而無需啓動演員系統。看起來你必須這樣做,所以你可以使用Akka測試包來控制這些角色並擁有測試角色系統。 也許從這裏的一些例子將有助於路線測試和特質組成: https://github.com/izmailoff/Spray_Mongo_REST_service/blob/master/rest/src/test/scala/com/example/service/GetTweetSpec。斯卡拉 –