簡體   English   中英

Dagger 2如何在Android上更輕松地進行測試?

[英]How does Dagger 2 make testing easier on Android?

使用DI的最大好處之一是它使測試變得更容易( 什么是依賴注入?也支持它)。 大多數DI框架,我與其他編程語言(工作的MEF.NET, 台風的OBJ-C /斯威夫特Laravel的IoC容器上的PHP,和其他一些),允許開發人員做一個單一的入口點寄存器相關對於每個組件,從而防止“創建”對象本身的依賴。

在我閱讀Dagger 2文檔之后,整個“無反思”的業務聽起來很棒,但我沒有看到它如何使測試變得更容易,因為對象仍然在創建自己的依賴項。

例如,在CoffeMaker示例中:

public class CoffeeApp {
  public static void main(String[] args) {

    // THIS LINE
    CoffeeShop coffeeShop = DaggerCoffeeShop.create();

    coffeeShop.maker().brew();
  } 
}

即使你沒有明確地調用new ,你仍然需要創建你的依賴。

現在,有關更詳細的示例,請轉到Android示例 如果你打開DemoActivity類,你會發現onCreate實現是這樣的:

@Override 
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
    // Perform injection so that when this call returns all dependencies will be available for use.
   ((DemoApplication) getApplication()).component().inject(this);
}

您可以清楚地看到DI組件與實際代碼沒有脫鈎。 總之,你需要mock / stub ((DemoApplication) getApplication()).component().inject(this); 在測試用例上(如果可能的話)。

到目前為止,我知道Dagger 2很受歡迎,所以我不會看到它。 那么Dagger 2如何讓測試課更容易? 我將如何模擬,假設我的活動所依賴的網絡服務類? 我希望答案盡可能簡單,因為我只對測試感興趣。

Dagger 2不會使測試更容易

...除了鼓勵你首先注入依賴關系之外,這自然會使個別類更容易測試。

最后我聽說,Dagger 2團隊仍在考慮改進測試支持的潛在方法 - 盡管正在進行任何討論,但它們似乎並不公開。

那么我該如何測試呢?

你指出想要明確使用Component的類依賴於它是正確的。 所以... 注入依賴! 你必須“手動”注入組件,但這不應該太麻煩。

官方的方式

目前,官方推薦的交換依賴項進行測試的方法是創建一個測試組件,擴展您的生產,然后在必要時使用自定義模塊。 像這樣的東西:

public class CoffeeApp {
  public static CoffeeShop sCoffeeShop;

  public static void main(String[] args) {
    if (sCoffeeShop == null) {
      sCoffeeShop = DaggerCoffeeShop.create();
    }

    coffeeShop.maker().brew();
  } 
}

// Then, in your test code you inject your test Component.
CoffeeApp.sCoffeeShop = DaggerTestCoffeeShop.create();

這種方法適用於您在運行測試時總是想要替換的內容 - 例如,您希望針對模擬服務器運行的網絡代碼,或者用於運行Espresso測試的IdlingResource實現。

非正式的方式

不幸的是,它的官方方式可能涉及很多樣板代碼 - 很好的一次性,但如果你只想換掉一個特定測試集的單個依賴項,真的很痛苦。

我最喜歡的黑客是簡單地擴展哪個Module有你想要替換的依賴項,然后覆蓋@Provides方法。 像這樣:

CoffeeApp.sCoffeeShop = DaggerCoffeeShop.builder()
    .networkModule(new NetworkModule() {
        // Do not add any @Provides or @Scope annotations here or you'll get an error from Dagger at compile time.
        @Override
        public RequestFactory provideRequestFactory() {
          return new MockRequestFactory();
        }
    })
    .build();

請查看此要點以獲取完整示例。

“允許開發人員在每個組件的單個入口點上注冊依賴項” - Dagger 2中的類似物是ModuleComponent ,您可以在其中定義依賴項。 優點是您不直接在組件中定義依賴項,從而將其解耦,以便稍后在編寫單元測試時,您可以使用測試component切換Dagger 2 component

“聽起來很棒”整個“沒有反思”的事業“ - ”沒有反思“的事情並不是關於匕首的”大不了“。 “大不了”是編譯時的完整依賴圖驗證。 其他DI框架沒有此功能,如果您無法定義如何滿足某些依賴項,您將在運行時遲到時收到錯誤。 如果錯誤位於一些很少使用的代碼路徑中,那么您的程序可能看起來是正確的,但在將來某個時候它會失敗。

“即使你沒有明確地調用new,你仍然需要創建你的依賴。” - 好吧,你總是要以某種方式啟動依賴注入。 其他DI可以“隱藏”/自動化此活動,但最后在某處構建圖形。 對於匕首1和2,這是在應用程序啟動時完成的。 對於main()中的“普通”應用程序(如示例中所示main() ,對於Android應用程序 - 在Application類中。

“你可以清楚地看到DI組件與實際代碼沒有脫鈎” - 是的,你是100%正確的。 這是因為您不直接控制Android中活動,片段和服務的生命周期,即操作系統為您創建這些對象,並且操作系統不知道您正在使用DI。 您需要手動注入活動,片段和服務。 起初這似乎很尷尬,但在現實生活中唯一的問題是,有時你可能忘記在onCreate()注入你的活動並在運行時獲得NPE。

暫無
暫無

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

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