简体   繁体   English

在Scala中以单子方式测试HttpRequest

[英]Testing HttpRequest in a monadic way in Scala

Suppose I would to test HTTP responses in Scala to make sure my web application returns them as required. 假设我将在Scala中测试HTTP响应,以确保我的Web应用程序根据需要返回它们。

For example, one response is required to have "status code" = Ok, "content-type: application/json" and "content-length" headers and a valid JSON body, another one is required to have "status code" = Bad Request and an error message, etc. 例如,要求一个响应具有“状态代码” =好,“内容类型:application / json”和“ content-length”标头以及有效的JSON正文,而另一个响应则必须具有“状态代码” =错误请求和错误消息等。

Suppose I have defined a few functions to test status, header, and body 假设我定义了一些函数来测试状态,标题和主体

def testStatus(status:Status): HttpResponse => Either[String, Status] = ...
 def doesHeaderExist(name: String): HttpResponse => Either[String, Header] = ...
 def testBody(body: Body): HttpResponse => Either[String, Body] = ...

 ... // etc.

Now I need to compose them to define a function to test a response. 现在,我需要组合它们以定义一个函数来测试响应。

I would like to do it in a monadic way, ie define a monad ResponseTest[A] 我想以单声道方式进行操作,即定义单声道 ResponseTest[A]

case class ResponseTest[A](req: HttpResponse, ea: Either[String, A]) {
  def unit(resp: HttpResponse, a: A) = ...
  def flatMap(f: A => ResponseTest[B]): ResponseTest[B] = ... 
}

re-define the test functions to return ResponseTest and compose them with the flatMap to define functions to test entire response 重新定义测试函数以返回ResponseTest并将其与flatMap以定义用于测试整个响应的函数

val testErrorResponse: HttpResponse => ResponseTest[HttpResponse] = ...
  val testJsonResponse: HttpResponse => ResponseTest[HttpResponse] = ...

Does it make sense ? 是否有意义 ? How would you suggest implement it? 您如何建议实施?

I would make the actions something like this: 我将采取以下措施:

def doesHeaderExist(name: String): HttpResponse => Try[HttpResponse]
def testBoxy(contents: String): HttpResponse => Try[HttpResponse]

Try composes, so if it fails, then what you wind up with is either something that has your final type in a Success or the exception (and failing test) in a Failure . Try撰写,因此如果失败,那么最终得到的要么是在Success中具有最终类型的东西,要么在Failure中具有最终类型的东西(并且测试Failure

val result = for{
 _1 <- doesHeaderExist("foo")(response)
 _2 <- testBody("bar")(_1)
} yield _2

result match{
  case Success(that) => //do stuff
  case Failure(ex) => //do stuff with the exception
}

And you handle the exception where it happened. 您可以处理发生的异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM