如何嘲笑斯卡拉剧框架外部WS API调用(how to mock external WS API c

2019-10-29 06:00发布

我有有一个REST API调用另一个外部REST API现有斯卡拉播放应用。 我想嘲笑外部Web服务返回假JSON数据,内部测试。 基于例如来自: https://www.playframework.com/documentation/2.6.x/ScalaTestingWebServiceClients

我跟着例子正是因为在文档和我得到的编译器错误因弃用类行动。

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的播放外部API的正确方法?

Answer 1:

你可以改变你的例子:

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%肯定,如果这是最好的方式。 不过,我已递交PR到播放的框架,所以你可能看从制造商评论认为空间。



Answer 2:

如果您使用的单机版游戏-WS,你可以使用这个库https://github.com/f100ded/play-fake-ws-standalone这样

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)
  }

}


文章来源: how to mock external WS API calls in Scala Play framework