2013-01-15 45 views
6

我想在Android功能测试它继承ActivityInstrumentationTestCase2使用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(); 
}` 

的onCreate方法,它是通过调用super.getActivity()解雇,不使用由TestModule提供的类。但是如果我手动运行我的活动(在测试环境之外),那么所有适当的类都由我的非测试模块提供/注入。

+0

所以它不容易看到这里发生了什么,因为我们没有看到你什么注射到测试等,您可以修剪和提供您的生产和测试模块的简化示例,它复制了这个问题? –

+0

也许我在这个相关的职位的回答可以帮助你: http://stackoverflow.com/questions/15630589/android-functional-testing-with-dagger?rq=1 – IIIRepublica

回答

3

我发现了一种由懒洋洋地创建对象图使用匕首ActivityInstrumentationTestCase2。我所做的就是等待创建对象图,直到第一次想要注入一个类为止,所以只要在调用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 
     }; 
    } 
} 

我们要注入的类里面,我们将简单地调用GraphHolder.getInstance().inject(this)而不是ObjectGraph.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创建依赖到你的TestCase而不是测试活动。什么你必须做的,是

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

+3

你不能注入从活动ActivityInstrumentationTestCase2,因为您必须调用getActivity()来获取对该活动的引用,并且会创建它(自动调用onCreate)。 因此,如果你在onCreate方法中进行注入,如果你尝试从ActivityInstrumentationTestCase2中设置它,注入依赖关系就太晚了。 IMO这是ActivityInstrumentationTestCase2中的一个巨大缺陷。你可以改用ActivityUnitTestCase。 –