首页 > 解决方案 > Scalamock:如何指定任意的元组序列

问题描述

我正在尝试为 Play 的 WSClient 创建一个模拟,如下所示:

  def mockGet[A](url : String, method : String, headers : Seq[(String, String)], timeout : Duration)(
    response: Future[AhcWSResponse]
  ) =
    (mockWsClient
      .url(_ : String)
        .withMethod(_ : String)
        .withHttpHeaders(_: (String, String)*)
        .withRequestTimeout(_ : Duration)
        .stream())
      .expects(url, method, headers, timeout)
      .returning(response)

问题是withHttpHeaders- 这实际上需要 (String, String)* 但是当我如上所述指定该类型时,我收到如下编译器错误:

[error]  found   : Seq[(String, String)]
[error]  required: (String, String)
[error]       .withHttpHeaders(_: Seq[(String, String)])

我需要为此方法指定什么类型,因为 (String, String) 不正确。这个方法的实际定义是:

  override def withHttpHeaders(headers: (String, String)*): Self

更新

我在@Mario 的建议之后尝试了这个:

  def mockGet[A](url: String, method: String, headers: Seq[(String, String)], timeout: Duration)(
    response: (String, String, Duration) => Future[ws.WSResponse]
  ) =
    (
      (
        xs: Seq[(String, String)]
      ) =>
        mockWsClient
          .url(_: String)
          .withMethod(_: String)
          .withRequestTimeout(_: Duration)
          .withHttpHeaders(xs: _*)
          .stream()
      )
      .expects(headers)
      .returning(response)

但这会使编译器崩溃:

[error] value x$1

标签: scalavariadic-functionsscalamock

解决方案


关键是要了解匿名函数占位符参数语法的工作原理。例如,给定

def f(i: Int*) = ???

然后

f(_: Int)

扩展到

(i: Int) => f(i)

因此尝试

def mockGet(headers : Seq[(String, String)) =
  ((xs: Seq[(String, String)]) => mockWsClient.withHttpHeaders(xs: _*)).expects(headers)

这是一个简化的例子

trait Zar {
  def f(i: Int*) = i
}

class ScalamockVarargsSpec extends FlatSpec with Matchers with MockFactory {
  "Varargs" should "be mockable" in {
    val zar = mock[Zar]
    ((xs: Seq[Int]) => zar.f(xs: _*)).expects(Seq(1,2))
    zar.f(1,2)
  }
}

在您的特定情况下,有多个匿名函数占位符参数,因此请尝试将它们全部展开,例如

def mockGet(url: String, headers : Seq[(String, String)) =
  ((u: String, xs: Seq[(String, String)]) => mockWsClient.url(u).withHttpHeaders(xs: _*))
    .expects(url, headers)

推荐阅读