Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Scala Play框架中模拟外部WS-API调用_Scala_Rest_Unit Testing_Playframework_Mocking - Fatal编程技术网

如何在Scala Play框架中模拟外部WS-API调用

如何在Scala Play框架中模拟外部WS-API调用,scala,rest,unit-testing,playframework,mocking,Scala,Rest,Unit Testing,Playframework,Mocking,我有一个现有的Scala play应用程序,它有一个调用另一个外部REST API的REST API。我想模拟外部Web服务返回假JSON数据进行内部测试。基于以下示例: 我完全按照文档中的示例进行操作,由于不推荐的类操作,我得到了编译器错误 import play.core.server.Server import play.api.routing.sird._ import play.api.mvc._ import play.api.libs.json._ import play.api.

我有一个现有的Scala play应用程序,它有一个调用另一个外部REST API的REST API。我想模拟外部Web服务返回假JSON数据进行内部测试。基于以下示例:

我完全按照文档中的示例进行操作,由于不推荐的类操作,我得到了编译器错误

import play.core.server.Server
import play.api.routing.sird._
import play.api.mvc._
import play.api.libs.json._
import play.api.test._

import scala.concurrent.Await
import scala.concurrent.duration._

import org.specs2.mutable.Specification
import product.services.market.common.GitHubClient

class GitHubClientSpec extends Specification {
  import scala.concurrent.ExecutionContext.Implicits.global

  "GitHubClient" should {
    "get all repositories" in {

      Server.withRouter() {
        case GET(p"/repositories") => Action {
          Results.Ok(Json.arr(Json.obj("full_name" -> "octocat/Hello-World")))
        }
      } { implicit port =>
        WsTestClient.withClient { client =>
          val result = Await.result(
            new GitHubClient(client, "").repositories(), 10.seconds)
          result must_== Seq("octocat/Hello-World")
        }
      }
    }
  }
}
不推荐使用包mvc中的对象操作:注入ActionBuilder (如DefaultActionBuilder)或扩展 BaseController/AbstractController/InjectedController


这是最新官方文档中的主要示例,其中实际上包含编译时错误,鉴于此示例不起作用,如何使用Scala Play轻松模拟外部API?

您可以将示例更改为:

Server.withRouterFromComponents() { cs => {
    case GET(p"/repositories") => cs.defaultActionBuilder {
      Results.Ok(Json.arr(Json.obj("full_name" -> "octocat/Hello-World")))
    }
  }
} { implicit port =>
  WsTestClient.withClient { client =>
    val result = Await.result(
      new GitHubClient(client, "").repositories(), 10.seconds)
    result should be(Seq("octocat/Hello-World"))
  }
}

老实说,我不是100%确定这是不是最好的方式。不过,我已向play framework提交了一份报告,以便您可以在该空间中查看制作人的评论。

您可以将示例更改为:

Server.withRouterFromComponents() { cs => {
    case GET(p"/repositories") => cs.defaultActionBuilder {
      Results.Ok(Json.arr(Json.obj("full_name" -> "octocat/Hello-World")))
    }
  }
} { implicit port =>
  WsTestClient.withClient { client =>
    val result = Await.result(
      new GitHubClient(client, "").repositories(), 10.seconds)
    result should be(Seq("octocat/Hello-World"))
  }
}

老实说,我不是100%确定这是不是最好的方式。不过,我已经向play框架提交了一个文件,这样您就可以在该空间中查看制作人的评论。

如果您使用的是play ws的独立版本,您可以像这样使用此库

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import org.f100ded.play.fakews._
import org.scalatest._
import play.api.libs.ws.JsonBodyWritables._

import scala.concurrent.duration.Duration
import scala.concurrent._
import scala.language.reflectiveCalls

/**
  * Tests MyApi HTTP client implementation
  */
class MyApiClientSpec extends AsyncFlatSpec with BeforeAndAfterAll with Matchers {

  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()
  import system.dispatcher

  behavior of "MyApiClient"

  it should "put access token to Authorization header" in {
    val accessToken = "fake_access_token"
    val ws = StandaloneFakeWSClient {
      case request @ GET(url"http://host/v1/foo/$id") =>
        // this is here just to demonstrate how you can use URL extractor
        id shouldBe "1"

        // verify access token
        request.headers should contain ("Authorization" -> Seq(s"Bearer $accessToken"))

        Ok(FakeAnswers.foo)
    }

    val api = new MyApiClient(ws, baseUrl = "http://host/", accessToken = accessToken)
    api.getFoo(1).map(_ => succeed)
  }

  // ... more tests

  override def afterAll(): Unit = {
    Await.result(system.terminate(), Duration.Inf)
  }

}

如果您使用的是play ws的独立版本,则可以像这样使用此库

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import org.f100ded.play.fakews._
import org.scalatest._
import play.api.libs.ws.JsonBodyWritables._

import scala.concurrent.duration.Duration
import scala.concurrent._
import scala.language.reflectiveCalls

/**
  * Tests MyApi HTTP client implementation
  */
class MyApiClientSpec extends AsyncFlatSpec with BeforeAndAfterAll with Matchers {

  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()
  import system.dispatcher

  behavior of "MyApiClient"

  it should "put access token to Authorization header" in {
    val accessToken = "fake_access_token"
    val ws = StandaloneFakeWSClient {
      case request @ GET(url"http://host/v1/foo/$id") =>
        // this is here just to demonstrate how you can use URL extractor
        id shouldBe "1"

        // verify access token
        request.headers should contain ("Authorization" -> Seq(s"Bearer $accessToken"))

        Ok(FakeAnswers.foo)
    }

    val api = new MyApiClient(ws, baseUrl = "http://host/", accessToken = accessToken)
    api.getFoo(1).map(_ => succeed)
  }

  // ... more tests

  override def afterAll(): Unit = {
    Await.result(system.terminate(), Duration.Inf)
  }

}