这里是scala noob。
我不理解来自Play应用程序集成测试(Scala)的以下代码:
package workflows.admin
import play.api.test._
class SignInSpec extends PlaySpecification {
"An activated user" should {
"be able to sign in to the admin console" in new WithBrowser(webDriver = WebDriverFactory(FIREFOX)) {
// some matchers here ...
true
}
}
}
据我所知,该示例从抽象类WithBrowser
创建了一个新的匿名类,并将其实例化。该实例将接收(命名的)构造函数参数webDriver
。
问题是,当我查看WithBrowser
时,我不明白发生了什么事:
abstract class WithBrowser[WEBDRIVER <: WebDriver](
val webDriver: WebDriver = WebDriverFactory(Helpers.HTMLUNIT),
val app: Application = GuiceApplicationBuilder().build(),
val port: Int = Helpers.testServerPort) extends Around with Scope {
def this(
webDriver: Class[WEBDRIVER],
app: Application,
port: Int) = this(WebDriverFactory(webDriver), app, port)
implicit def implicitApp: Application = app
implicit def implicitPort: Port = port
lazy val browser: TestBrowser = TestBrowser(webDriver, Some("http://localhost:" + port))
override def around[T: AsResult](t: => T): Result = {
try {
Helpers.running(TestServer(port, app))(AsResult.effectively(t))
} finally {
browser.quit()
}
}
}
我有两个问题:
WithBrowser
是带有类型参数WEBDRIVER
的泛型抽象类,但是在示例中未声明类型参数。相反,匿名类的实例使用命名的构造函数参数webDriver
接收此信息。类型参数和构造函数参数之间缺少什么链接?true
),并且该代码块是测试本身。但是,该代码在匿名类中位于何处? WithBrowser
扩展了Around
并覆盖了around
函数,该函数执行代码块,但是我不明白所生成的匿名类如何将给定的示例代码块移动到around
中。我们非常感谢您的帮助。
答案 0 :(得分:1)
Scala可以推断类型参数。由于传递的参数的类型都不与类型参数相关,因此将限制要推断的类型,因此scala编译器只会将其推断为类型Nothing
。
代码块通常是该类的构造函数,但这是一种特殊情况。 Around
类确实扩展了scala.DelayedInit
接口。这会将构造函数中的代码重写为delayedInit
函数的调用。实际上是构造函数的代码将作为按名称调用参数传递给此函数。该值(实际上包装在org.specs2.execute.Result.resultOrSuccess
调用中)是传递给around
函数的参数。
像这样想象Around
类:
class Around extends DelayedInit {
def delayedInit(f: => Unit): Unit = around(f)
def around(f: => Unit): Unit
}
假设您现在将继承周围类:
class Foo extends Around {
println("Hello World")
}
上面的内容被重写为此:
class Foo extends Around {
delayedInit(println("Hello World"))
}
如果我的解释不够清楚,或者您想了解更多实施细节:
-这是Around
和DelayedInit
文档。