玩框架WSClient测试

时间:2019-06-24 12:32:08

标签: scala testing playframework ws-client

我的代码中有一个服务类,例如UserService。它有一个WSClient成员,该成员对Web服务进行调用。我想为UserService方法编写测试用例。

我对测试WSClient进行了一些研究,但是没有找到像我这样的用例。我应该建立实时测试服务还是进行模拟?这是另一个问题。

mydata=read.csv("irelandish.csv")
height=mydata$i_h100
breaks=seq(2,30,by=2)  #2m intervals
height.cut=cut(height, breaks, right=TRUE)

#attempt at calculating means per group
install.packages("dplyr")
mean=summarise(group_by(cut(height, breaks, right=TRUE), 
mean(mydata$i_cd)))
install.packages("reshape2")
dcast(mean)

这些方法使用WSClient调用Web服务端点。

我想为这些方法编写测试用例。设置测试服务并调用它或模拟WSClient哪个是最好的?

1 个答案:

答案 0 :(得分:0)

我已经创建了一个CustomWSClient,CustomWSRequest和CustomWSResponse以用于测试,如下所示。

package unittest

import play.api.http.Writeable
import play.api.libs.iteratee.Enumerator
import play.api.libs.json.{JsValue, Json}
import play.api.libs.ws._

import scala.concurrent.Future
import scala.xml.Elem

class CustomWSClient extends WSClient {

  var t: ResponseObject = new ResponseObject(Json.toJson("Success"), Map("trial" -> Seq("value")), 200)

  override def underlying[T]: T = underlying.asInstanceOf[T]

  override def url(url: String): WSRequest = {
    var c: CustomWSRequest = CustomWSRequest(url, t)
    c.setResponse(t)
    c
  }

  override def close(): Unit = {}
  def setResponse(t: ResponseObject) = {
    this.t = t
  }

}

case class CustomWSRequest(inputUrl: String, t: ResponseObject) extends WSRequest {
  override val url: String = inputUrl

  override def withHeaders(hdrs: (String, String)*): WSRequest = { this }

  override def withAuth(username: String, password: String, scheme: WSAuthScheme): WSRequest = { this }

  override def withQueryString(parameters: (String, String)*): WSRequest = { this }

  override def execute(): Future[WSResponse] = { Future.successful(CustomWSResponse(t)) }

  override def sign(calc: WSSignatureCalculator): WSRequest = { this }

  override def stream(): Future[(WSResponseHeaders, Enumerator[Array[Byte]])] = null

  override def withVirtualHost(vh: String): WSRequest = { this }

  override def withMethod(method: String): WSRequest = { this }

  override def withRequestTimeout(timeout: Long): WSRequest = { this }

  override def withProxyServer(proxyServer: WSProxyServer): WSRequest = { this }

  override def withFollowRedirects(follow: Boolean): WSRequest = { this }

  override def withBody(body: WSBody): WSRequest = { this }

  override def get(): Future[WSResponse] = { Future.successful(CustomWSResponse(t)) }

  override def post[T](body: T)(implicit wrt: Writeable[T]) = { Future.successful(CustomWSResponse(t)) }

  //override def put[T](body: T)(implicit wrt: Writeable[T]) = {Future.successful( CustomWSResponse(t))}

  def setResponse(t: ResponseObject) = {
    t
  }


  override val calc: Option[WSSignatureCalculator] = None
  override val queryString: Map[String, Seq[String]] = Map("trial" -> Seq("value"))
  override val method: String = "TestMethod"
  override val followRedirects: Option[Boolean] = None
  override val body: WSBody = null
  override val requestTimeout: Option[Int] = None
  override val virtualHost: Option[String] = None
  override val proxyServer: Option[WSProxyServer] = None
  override val auth: Option[(String, String, WSAuthScheme)] = None
  override val headers: Map[String, Seq[String]] = Map("trial" -> Seq("value"))

}

case class CustomWSResponse(t: ResponseObject) extends play.api.libs.ws.WSResponse {
  def allHeaders: Map[String, Seq[String]] = { t.headers }

  def statusText: String = { "success" }

  def underlying[T]: T = underlying.asInstanceOf[T]

  def body: String = { t.json.toString() }

  def header(key: String): Option[String] = Option(t.headers.get(key).headOption.get.apply(0))

  def cookie(name: String): Option[WSCookie] = Some(CustomWSCookie("test"))

  def status: Int = { t.status }
  def json: JsValue = t.json

  override def cookies: Seq[WSCookie] = Seq(CustomWSCookie("test"))

  override def xml: Elem = null

  override def bodyAsBytes: Array[Byte] = null
}

case class CustomWSCookie(t: String) extends play.api.libs.ws.WSCookie {

  override def underlying[T]: T = this.underlying

  override def domain: String = "test"

  override def name: Option[String] = Some("test")

  override def value: Option[String] = Some("test")

  override def path: String = "test"

  override def expires: Option[Long] = Some(2L)

  override def maxAge: Option[Int] = Some(5)

  override def secure: Boolean = true
}

case class ResponseObject(json: JsValue, headers: Map[String, Seq[String]], status: Int)

我在使用ws对象的地方创建了一个模拟。

class TranslationsActorSpec extends ServiceOneAppPerSuite with LazyLogging {

  override val ws = mock[CustomWSClient]
  val mockWSRequest = mock[CustomWSRequest]
  val mockWSResponse = mock[CustomWSResponse]

  when(ws.url("https://getCallToMyService")) thenReturn (mockWSRequest)
  when(mockWSRequest.withHeaders(
    "Authorization" -> "token somevalue"
  )) thenReturn (mockWSRequest)
  when(mockWSRequest.get()) thenReturn (Future.successful(mockWSResponse))
  when(mockWSResponse.status) thenReturn (200)
  //write your testcase and pass ws object to it, it will get the mocked response for the service call
}