如何在测试期间调用oncreate之前获取活动引用

时间:2015-07-13 16:39:41

标签: android mocking android-testing android-espresso junit-rule

如何在调用onCreate之前获取Activity的引用。而它的测试。我使用ActivityTestRule作为JUnit规则。这个要求的原因是我想从测试中将Mocks注入活动。

public class MyActivity extends Activity{

    MyComponent myComponent;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if(myComponent==null){
            myComponent ... //initialise dagger component
        }
        myComponent.inject(this);
        ...
    }

    public void setComponent(MyComponent comp){
        this.myComponent = comp;
    }
}

public class MyTest{

    @Rule
    public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class);


    MyComponent myFakeComponent;

    @Before                                      
    public void setUp() {                        
        MyActivity activity = intentsTestRule.getActivity();  
        activity.setComponent(myFakeComponent);
    }                                            

    @Test
    public void testMethod1(){...}
} 

3 个答案:

答案 0 :(得分:17)

根据文档,你在这里做的是错误的。

@Rule
public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class);

MyComponent myFakeComponent;

@Before                                      
public void setUp() {                        
    MyActivity activity = intentsTestRule.getActivity();  
    activity.setComponent(myFakeComponent);
}              

由于,

  

此规则提供单个活动的功能测试。   在每次测试注释之前,将启动测试中的活动   在使用@Before。注释的方法之前进行测试和   它将在测试完成和方法后终止   用After注释完成。在测试期间   你将能够直接操纵你的活动。

然而!

protected void beforeActivityLaunched ()
  

重写此方法以执行应运行的任何代码   在创建和启动活动之前。   在每种测试方法之前调用此方法,   包括用@Before注释的任何方法。

因此,如果将活动外的MainActivityComponent初始化移动到可模拟的位置,那么您将能够在创建主活动之前将它修改在一起。

编辑:

另一种可能的解决方案是按照link懒惰地启动活动。

@Rule
public ActivityTestRule<NoteDetailActivity> mNoteDetailActivityTestRule =
        new ActivityTestRule<>(NoteDetailActivity.class, true /* Initial touch mode  */,
                false /* Lazily launch activity */);

@Before
public void intentWithStubbedNoteId() {
   // Add a note stub to the fake service api layer.
   FakeNotesServiceApiImpl.addNotes(NOTE);

   // Lazily start the Activity from the ActivityTestRule this time to inject the start Intent
   Intent startIntent = new Intent();
   startIntent.putExtra(NoteDetailActivity.EXTRA_NOTE_ID, NOTE.getId());
   mNoteDetailActivityTestRule.launchActivity(startIntent);

   registerIdlingResource();
}

答案 1 :(得分:1)

以下是我的示例代码:

public class TestClass {

    @Rule
    public ActivityTestRule<T> activityRule = new ActivityTestRule<T>(type) {
            @Override
            protected void beforeActivityLaunched() {
                //TODO inject mocks, setup stubs etc..
            }
        };
    }

    @Before
    public void before() {
        activityRule.getActivity();
    }

    @Test
    public void myTest() {
        //...
    }


}

答案 2 :(得分:0)

此代码是否完整?我无法看到你创建匕首图。 无论如何,我在我的代码中做的是有一个名为Injector的静态类,它为我创建图形,并且还可以将元素注入对象。因此,在我的应用程序类中,我将其称为创建图形,而所有其他活动仅使用现有图形。

然后,在测试中,您可以创建一个虚假的测试应用程序类,以不同的方式初始化图形,或者只是在创建活动之前重新创建调用Injector方法的图形。我对ActivityTestRule并不熟悉,所以我对这个测试的生命周期没什么帮助。

但是,只需确保在创建活动之前创建新图表,然后让活动使用现有图表。 活动如何访问图表?好吧,我并不喜欢它,但我们习惯于访问应用程序类(使用显式转换)并要求它为我们注入依赖项。这就是Dagger的例子也是如此。