我认为,总的来说,您已经想到了最好的方法是模拟响应。在Scala中,可以使用Scala Mock http://scalamock.org/完成。
如果您安排代码以便将您的实例akka.http.scaladsl.HttpExt
依赖注入到使用它的代码中(例如,作为构造函数参数),那么在测试期间,您可以注入的实例,mock[HttpExt]
而不是使用Http
apply方法构建的实例。
编辑:我想这是因为不够具体而被否决。这是我如何模拟您的方案。所有的隐式函数使它变得更加复杂。
代码在main
:
import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model.{Uri, HttpResponse, HttpRequest} import akka.http.scaladsl.unmarshalling.Unmarshal import akka.stream.ActorMaterializer import scala.concurrent.{ExecutionContext, Future} trait S3BucketTrait { type HttpResponder = HttpRequest => Future[HttpResponse] def responder: HttpResponder implicit def actorSystem: ActorSystem implicit def actorMaterializer: ActorMaterializer implicit def ec: ExecutionContext def sampleTextFile(uri: Uri): Future[String] = { val responseF = responder(HttpRequest(uri = uri)) responseF.flatMap { response => Unmarshal(response.entity).to[String] } } } class S3Bucket(implicit val actorSystem: ActorSystem, val actorMaterializer: ActorMaterializer) extends S3BucketTrait { override val ec: ExecutionContext = actorSystem.dispatcher override def responder = Http().singleRequest(_) }
代码在test
:
import akka.actor.ActorSystem import akka.http.scaladsl.model._ import akka.stream.ActorMaterializer import akka.testkit.TestKit import org.scalatest.{BeforeAndAfterAll, WordSpecLike, Matchers} import org.scalamock.scalatest.MockFactory import scala.concurrent._ import scala.concurrent.duration._ import scala.concurrent.Future class S3BucketSpec extends TestKit(ActorSystem("S3BucketSpec")) with WordSpecLike with Matchers with MockFactory with BeforeAndAfterAll { class MockS3Bucket(reqRespPairs: Seq[(Uri, String)]) extends S3BucketTrait{ override implicit val actorSystem = system override implicit val ec = actorSystem.dispatcher override implicit val actorMaterializer = ActorMaterializer()(system) val mock = mockFunction[HttpRequest, Future[HttpResponse]] override val responder: HttpResponder = mock reqRespPairs.foreach{ case (uri, respString) => val req = HttpRequest(HttpMethods.GET, uri) val resp = HttpResponse(status = StatusCodes.OK, entity = respString) mock.expects(req).returning(Future.successful(resp)) } } "S3Bucket" should { "Marshall responses to Strings" in { val mock = new MockS3Bucket(Seq((Uri("http://example.com/1"), "Response 1"), (Uri("http://example.com/2"), "Response 2"))) Await.result(mock.sampleTextFile("http://example.com/1"), 1 second) should be ("Response 1") Await.result(mock.sampleTextFile("http://example.com/2"), 1 second) should be ("Response 2") } } override def afterAll(): Unit = { val termination = system.terminate() Await.ready(termination, Duration.Inf) } }
build.sbt
依赖项:
libraryDependencies += "com.typesafe.akka" % "akka-http-experimental_2.11" % "2.0.1" libraryDependencies += "org.scalamock" %% "scalamock-scalatest-support" % "3.2" % "test" libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.6" libraryDependencies += "com.typesafe.akka" % "akka-testkit_2.11" % "2.4.1"