2013-01-15 14 views
6

ActivityInstrumentationTestCase2を継承するAndroid機能テストでDaggerを使用しようとしています。ダガーはActivityInstrumentationTestCase2テストの依存性注入をサポートしていますか

セットアップコードは次のようになります。

@Override 
protected void setUp() { 
    // TODO Auto-generated method stub 
    try { 
     super.setUp(); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    ObjectGraph.create(new TestModule()).inject(this); 
    this.activity = super.getActivity(); 
}` 

super.getActivity()を呼び出すことによって発射されたOnCreateの方法、TestModuleによって提供されるクラスを使用していません。しかし、私が手動で(テスト環境の外で)アクティビティを実行すると、適切でないすべてのクラスが私の非テストモジュールによって提供/注入されます。

+0

だから、あなたがトリムと提供できますなど、私たちはあなたがテストに注入しているものを見ていないので、ここで起こっているかを見るために簡単ではありませんこの問題を再現する実動モジュールとテストモジュールの簡単な例? –

+0

たぶん、この関連記事の私の答えは、次のことに役立ちます。 http://stackoverflow.com/questions/15630589/android-functional-testing-with-dagger?rq=1あなたからの活動に注入することはできません – IIIRepublica

答えて

3

です。私が行うことは、クラスが初めて注入されるまでObject Graphを作成することです。つまり、getActivity()(テスト対象のアクティビティのアクティビティライフサイクルを開始する)を呼び出す前にモジュールを追加し、overrides = trueをテストモジュール、これは動作します。関連するクラスとスニペットは次のとおりです。

GraphHolderは、名前が示すとおり、ObjectGraphオブジェクトを保持しています。 ObjectGraphではなく、このクラスへのすべての呼び出しを行います。

public class GraphHolder { 

    private static GraphHolder sInstance; 

    private Object[] mModules; 
    private ObjectGraph mGraph; 

    private GraphHolder() { 
    } 

    public static GraphHolder getInstance() { 
     if (sInstance == null) { 
      sInstance = new GraphHolder(); 
     } 

     return sInstance; 
    } 

    public void inject(Object object) { 
     if (mGraph == null) { 
      create(); 
     } 

     mGraph.inject(object); 
    } 

    public <T> T get(Class<T> type) { 
     if (mGraph == null) { 
      create(); 
     } 

     return mGraph.get(type); 
    } 

    public void addModules(Object... modules) { 
     if (mGraph != null) { 
      mGraph.plus(modules); 
     } else { 
      if (mModules == null) { 
       mModules = modules; 
      } else { 
       mModules = concatenate(mModules, modules); 
      } 
     } 
    } 

    private void create() { 
     mGraph = ObjectGraph.create(mModules); 
     mModules = null; 
    } 

    private Object[] concatenate(Object[] a, Object[] b) { 
     int aLength = a.length; 
     int bLength = b.length; 

     Object[] c = new Object[aLength + bLength]; 
     System.arraycopy(a, 0, c, 0, aLength); 
     System.arraycopy(b, 0, c, aLength, bLength); 

     return c; 
    } 
} 

我々はApplicationクラスで私たちのモジュールを追加します:

我々は注入したいクラスインサイド
public class MyApplication extends Application { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     GraphHolder.getInstance().addModules(getModules()); 
    } 

    Object[] getModules() { 
     return new Object[]{ 
       // your modules here 
     }; 
    } 
} 

、我々は単に私たちのテストモジュールでObjectGraph.inject(this)

ではなくGraphHolder.getInstance().inject(this)と呼ぶことにしますテストのためにオーバーライドするオブジェクトを提供し、overrides = true@Moduleアノテーションに追加します。これは、競合がある場合、他のモジュールよりもこのモジュールのプロバイダを優先させるためにオブジェクトグラフに指示します。

その後、我々のテストで:

@Inject Foo mFoo; 

@Override 
public void setUp() { 
    super.setUp(); 
    GraphHolder.getInstance().addModules(new TestFooModule()); 
    GraphHolder.getInstance().inject(this); // This is when the object graph will be created 
} 
1

ObjectGraph.create(new TestModule()).inject(this);

このコードは、あなたのテストケースの代わりに、テスト活動にTestModuleによって作成された依存関係を注入しようとしています。あなたはここで行う必要があるだろうと、私は怠惰オブジェクトグラフを作成することにより、ActivityInstrumentationTestCase2でダガーを使用する方法を発見し

ObjectGraph.create(new TestModule()).inject(this.activity);

+3

アクティビティへの参照を取得するためにgetActivity()を呼び出さなければならないため、それを作成します(自動的にonCreateを呼び出す)。 したがって、onCreateメソッドで注入を行うと、ActivityInstrumentationTestCase2からこれを設定しようとすると依存関係を注入するのが遅すぎます。 IMOこれはActivityInstrumentationTestCase2の大きな欠陥です。 ActivityUnitTestCaseを代わりに使用できます。 –