使用复杂对象编写 Given/Then/When 规范

Writing Given/Then/When specs with complex objects

我正在尝试在完全支持的情况下使用 GWT 规范,但其 official documentation 的示例有点简单。

在 SO 中搜索我发现了这个问题:

但它太老了(3 年),我认为 specs2GWT 的做法已经改变。

到目前为止我有这个简单的测试:

class FlowCollectorSpec extends Specification
  with GWT
  with StandardRegexStepParsers { def is = s2"""

 Given a API route to get flows                                             ${apiCaller.start}
   Given an access to the API URL: http://192.168.56.102:8080/stats/flow/
   When getting flow stats for a switch with id: 1
   Then status code should be: 200                                          ${apiCaller.end}
"""

  val anAPIUri = readAs(".*: (.*)$").and((s: String) => s)

  val apiCaller =
    Scenario("apiCaller").
      given(aString).
      given(anInt).
      when(anAPIUri) {case url :: dpid :: _ => FlowCollector.getSwitchFlows(dpid)}.
      andThen(anInt) {case expected :: actual :: _ => actual.code must_== expected}
}

如何在 Given 语句中指定复杂对象?像这样:

Given a Json response: ${jsonResponse}

我终于想到了一个解决方案,我不知道这样做是否正确,但目前它正在工作:

class FlowCollectorSpec extends Specification
  with GWT
  with StandardRegexStepParsers { def is = s2"""

 Given a API route to get flows                                             ${connectTest.start}
  Given an access to the API URL: http://192.168.56.102:8080/stats/flow/
  When getting flow stats for a switch with id: 1
  Then status code should be: 200                                          ${connectTest.end}

 Retrieving values                                                          ${gettingValues.start}
  Given an api call response: {"1": [{"actions": ["OUTPUT:CONTROLLER"], "idle_timeout": 0, "cookie": 0, "packet_count": 1212, "hard_timeout": 0, "byte_count": 72720, "duration_sec": 432, "duration_nsec": 903000000, "priority": 65535, "length": 96, "flags": 0, "table_id": 0, "match": {"dl_type": 35020, "dl_dst": "01:80:c2:00:00:0e"}}, {"actions": ["OUTPUT:CONTROLLER"], "idle_timeout": 0, "cookie": 0, "packet_count": 49, "hard_timeout": 0, "byte_count": 3890, "duration_sec": 432, "duration_nsec": 938000000, "priority": 0, "length": 80, "flags": 0, "table_id": 0, "match": {}}]}
  When extracting key: packet_count
  Then a field look up should return: true                                  ${gettingValues.end}
"""

  val stepParser = readAs(".*: (.*)$").and((s: String) => s)
  val jsonExtractor = readAs(".+?: (.*)").and((s:String) => JsonParser(s).asJsObject)
  val aJsonKey = aString

  val connectTest =
    Scenario("connectTest").
      given(aString).
      given(anInt).
      when(stepParser) {case url :: dpid :: _ => FlowCollector.getSwitchFlows(dpid)}.
      andThen(anInt) {case expected :: actual :: _ => actual.code must_== expected}

  val gettingValues =
    Scenario("Getting Values").
      given(jsonExtractor).
      when(aJsonKey) { case key :: json :: _ => json.fields contains key}.
      andThen(){
        case expected :: exists :: _ =>
          if (expected == "true") exists must_== true
          else exists must_==false
      }
}

如果你的数据很复杂,无法在一行中显示,你可以简单地写

 class FlowCollectorSpec extends Specification
  with GWT
  with StandardRegexStepParsers { def is = s2"""

 Given a API route to get flows                                                 ${apiCaller.start}
   Given an access to the API URL:     http://192.168.56.102:8080/stats/flow/
   Given some complex data
   When getting flow stats for a switch with id: 1
   Then status code should be: 200                                              ${apiCaller.end}
"""

  val anAPIUri = readAs(".*: (.*)$").and((s: String) => s)

  val apiCaller =
    Scenario("apiCaller").
      given(aString).
      given(complexData).
      given(anInt).
      when(anAPIUri) { case url :: Json(j) :: dpid :: _ => FlowCollector.getSwitchFlows(dpid) }.
      andThen(anInt) { case expected :: actual :: _ => actual.code must_== expected }

  val complexData = readAs(".*").andThen(_ => Json("some json"))

  case class Json(value: String)

  object FlowCollector {
    def getSwitchFlows(dpid: Int) = FlowResult(code = 200)
  }

  case class FlowResult(code: Int)
}

否则你的解决方案就是正确的。