[英]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 run
或sbt start
執行此操作sbt run
預期。 但是,當我嘗試使用sbt test
或sbt 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
(或其他)似乎會“忘記”所有內置的依賴項注入配置。 不幸的是,我在這里或其他任何地方都找不到任何適用的信息,這些信息會導致我找到解決方案。
問題:
任何見識和幫助,不勝感激! 親切的問候,德克
更新這是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.