文件

§使用編譯時期相依性注入進行測試

如果您手動連接應用程式或使用 編譯時期相依性注入,則您可以直接使用和自訂應用程式元件,或建立特定於測試案例的測試變體。您也可以修改和覆寫篩選器、定義路由,以及指定組態。

§BuiltInComponentsFromContext

BuiltInComponentsFromContext 提供一種簡單的方法來引導您的元件。在給定背景下,這會提供所有必要的內建元件:environmentconfigurationapplicationLifecycle 等。

編譯時依賴注入 中所述,這是手動連接應用程式的最常見方式。

在測試時,我們可以使用允許我們啟動完整應用程式進行完整功能測試的實際元件,或者我們可以建立一個根據需要啟動應用程式子集的測試元件。

§WithApplicationComponents

測試元件的關鍵是 WithApplicationComponents 特質。這會設定應用程式、伺服器和內容,以準備進行測試。有許多 子特質 可用於混合,具體取決於您的測試策略
* OneAppPerSuiteWithComponents
* OneAppPerTestWithComponents
* OneServerPerSuiteWithComponents
* OneServerPerTestWithComponents

建議您熟悉每個 特質 的文件,以決定哪一個最符合您的需求。

§內聯定義元件

如前所述,元件可以在測試中內聯定義。為此,只需覆寫元件並完成 BuiltInComponentsFromContext 的實作,提供路由器即可。

override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {

  import play.api.mvc.Results
  import play.api.routing.Router
  import play.api.routing.sird._

  lazy val router: Router = Router.from({
    case GET(p"/") =>
      defaultActionBuilder {
        Results.Ok("success!")
      }
  })
  override lazy val configuration: Configuration =
    Configuration("foo" -> "bar", "ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
}

上述
* 我們在實作中定義匯入,以防止在斷言動詞時 sirdplay.api.http 套件之間發生衝突。
* 我們定義一個測試路由器並實作適當的路由,在這種情況下,我們匹配根補丁。
* 我們覆寫組態以提供要在測試中使用的其他值,這當然是可選的。

§使用現有元件

如果我們想要使用現有的應用程式元件,我們可以在測試中直接實例化它們。

override def components: BuiltInComponents = new SomeAppComponents(context)

此外,也可以在這個階段覆寫 components 中的任何定義,例如提供額外的設定或模擬資料庫。

override def components: BuiltInComponents = new SomeAppComponents(context) {
  override lazy val configuration: Configuration =
    Configuration("ehcacheplugin" -> "enabled").withFallback(context.initialConfiguration)
}

§完整的範例

class ExampleComponentsSpec extends PlaySpec with OneAppPerSuiteWithComponents {

  // #scalacomponentstest-inlinecomponents
  override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {

    import play.api.mvc.Results
    import play.api.routing.Router
    import play.api.routing.sird._

    lazy val router: Router = Router.from({
      case GET(p"/") =>
        defaultActionBuilder {
          Results.Ok("success!")
        }
    })
    override lazy val configuration: Configuration =
      Configuration("foo" -> "bar", "ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
  }
  // #scalacomponentstest-inlinecomponents

  "The OneAppPerSuiteWithComponents trait" must {
    "provide an Application" in {
      import play.api.test.Helpers.GET
      import play.api.test.Helpers.route
      val Some(result: Future[Result]) = route(app, FakeRequest(GET, "/"))
      Helpers.contentAsString(result) must be("success!")
    }
    "override the configuration" in {
      app.configuration.getOptional[String]("foo") mustBe Some("bar")
    }
  }
}

§巢狀規格

如果你有許多可以共用同一個 Application 的測試,而且你不想將它們全部放入一個測試類別中,你可以將它們放入不同的 Suite 類別中。這些將會是你的巢狀套件。建立一個延伸適當 trait 的主套件,例如 OneAppPerSuiteWithComponents,並宣告巢狀 Suite。最後,使用 @DoNotDiscover 標註巢狀套件,並讓它們延伸 ConfiguredApp。以下是一個範例

class NestedExampleSpec
    extends Suites(new OneSpec, new TwoSpec, new RedSpec, new BlueSpec)
    with OneAppPerSuiteWithComponents
    with TestSuite {

  override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {

    import play.api.mvc.Results
    import play.api.routing.Router
    import play.api.routing.sird._

    lazy val router: Router = Router.from({
      case GET(p"/") =>
        defaultActionBuilder {
          Results.Ok("success!")
        }
    })

    override lazy val configuration: Configuration =
      Configuration("ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
  }
}

// These are the nested suites
@DoNotDiscover class OneSpec extends PlaySpec with ConfiguredApp {
  "OneSpec" must {
    "make the Application available implicitly" in {
      def getConfig(key: String)(implicit app: Application) = app.configuration.getOptional[String](key)

      getConfig("ehcacheplugin") mustBe Some("disabled")
    }
  }

}

@DoNotDiscover class TwoSpec extends PlaySpec with ConfiguredApp

@DoNotDiscover class RedSpec extends PlaySpec with ConfiguredApp

@DoNotDiscover class BlueSpec extends PlaySpec with ConfiguredApp {

  "The NestedExampleSpec" must {
    "provide an Application" in {
      import play.api.test.Helpers.GET
      import play.api.test.Helpers.route
      val Some(result: Future[Result]) = route(app, FakeRequest(GET, "/"))
      Helpers.contentAsString(result) must be("success!")
    }
  }
}

下一步:使用資料庫進行測試


在此文件中發現錯誤?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件指南 後,請隨時提交拉取請求。有問題或建議要分享?前往 我們的社群論壇 與社群展開對話。