簡體   English   中英

如果添加了模塊,則Play 2.4依賴注入會忘記單元測試中的內置類

[英]Play 2.4 dependency injection forgets about builtin classes in unit tests if modules are added

我們正在將僅Java的Play應用程序從Play 2.4遷移到Play 2.5。 第一步:擺脫GlobalSettings ,仍然完全在2.4領域中。 我寫了一些StartModule ,它將取代遷移指南和“ Internet”描述的功能。 我加

play.modules.enabled += "de.[...].modules.StartModule"

到應用程序的.conf文件。 通過sbt runsbt start執行此操作sbt run預期。 但是,當我嘗試使用sbt testsbt test-only sbt test sbt test-only時,會出現大量問題。

由於應用程序很復雜並且具有大量的遺留部分,因此我們有一個相當詳細的單元測試設置。 最終,Play服務器的單元測試實例開始於

Helpers.start(testserver=Helpers.testServer(playhttpport,
    app=new GuiceApplicationBuilder()
      .configure(getConfiguration())
      .build()));

只要上面的play.modules.enabled行對於單元測試代碼不可見,就可以使用。 啟用后,我會收到許多錯誤消息,例如

Test de.[...]Tests failed: com.google.inject.CreationException:
   Unable to create injector, see the following errors:

1) No implementation for play.inject.ApplicationLifecycle was bound.
   while locating play.inject.ApplicationLifecycle

要么

2) Could not find a suitable constructor in play.api.Environment.
   Classes must have either one (and only one) constructor annotated with @Inject
   or a zero-argument constructor that is not private.

如果我刪除play.modules.enabled行並將服務器啟動更改為同樣的事情,也會發生

Helpers.start(testserver=Helpers.testServer(playhttpport,
  app=new GuiceApplicationBuilder()
    .load(Guiceable.modules(new StartModule()))
    .configure(getConfiguration())
    .build()));

在我有限的理解中,如果給出了任何其他依賴項定義, GuiceApplicationBuilder (或其他)似乎會“忘記”所有內置的依賴項注入配置。 不幸的是,我在這里或其他任何地方都找不到任何適用的信息,這些信息會導致我找到解決方案。

問題:

  1. 我的分析正確嗎?
  2. 如何通過DI框架中的附加模塊使單元測試代碼正常工作?
  3. 直接在Play 2.5中繼續會有所幫助嗎? 我想先解決這個問題,因為遷移步驟將帶來很多處理工作,而我確實為此具有功能基礎-包括可操作的單元測試框架...

任何見識和幫助,不勝感激! 親切的問候,德克

更新這是StartModule

public class StartModule extends AbstractModule {
  @Override protected void configure() {
    bind(InnerServerLauncher.class).asEagerSingleton();
  }
}

這是InnerServerLauncher

@Singleton
public class InnerServerLauncher {
  @Inject
  public InnerServerLauncher(ApplicationLifecycle lifecycle,
                             Environment environment) {
    System.err.println("*** Server launcher called ***");
  }
}

我應該補充一點,如果我將完全不同的類放到play.modules.enabled也會出現問題

play.modules.enabled += "play.filters.cors.CORSModule"

好的,我終於明白了。 問題是我上面提到的但沒有進一步闡述的configuration()方法。 正如我說的,我們的系統中有很多遺產。 因此,我們有一種機制可以獨立於Play的配置文件來構建單元測試的配置。 GuiceBuilder.configure() (以及基於fakeApplication()的方法)將其與Play-internal配置合並, 但僅在最頂層 對於普通設置(字符串,數字等)可以,但是對於值列表,則意味着完整列表將被覆蓋並替換

Play內部使用play.modules.enabled來收集必須在依賴項注入框架中注冊的默認模塊。 文檔非常清楚地指出,您在application.conf中的語句必須僅向play.modules.enabled添加元素,即

play.modules.enabled += "package.Module"

但是,我們為單元測試構建配置環境的“特殊方式”會在設置好我們自己的配置中的任何值后立即覆蓋 Play自己的play.modules.enabled 這就破壞了Play的完整依賴項注入方案,因為不再可以訪問其自己的基類。 mm!

我通過使用一個“真實的”配置文件解決了這一問題,該文件由GuiceApplicationBuilder正常讀取,並包含那些play.modules.enabled += ...行。 由於此配置文件仍是針對單元測試場景而臨時生成的,因此我將其名稱通過System.setProperty傳遞給GuiceApplicationBuilder

System.setProperty("config.file",conffilename);
Helpers.start(testserver=Helpers.testServer(playhttpport,
  app=new GuiceApplicationBuilder().build()));

現在,正確創建了配置,並使用 play.modules.enabled的內部默認設置。 現在,我終於可以開始將代碼從GlobalSettings實際移至已注入並熱切加載的模塊中。 狩獵只有十個小時...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM