10

如何在调用 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(){...}
} 
4

3 回答 3

19

根据文档,您在这里所做的事情是错误的。

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

MyComponent myFakeComponent;

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

因为,

此规则提供单个活动的功能测试。被测活动将在使用 Test 注释的每个测试之前以及在使用 @Before 注释的方法之前启动。 它会在测试完成并且用 After 注解的方法完成后终止。在测试期间,您将能够直接操作您的活动。

然而!

protected void beforeActivityLaunched ()

覆盖此方法以执行应在创建和启动 Activity 之前运行的任何代码。此方法在每个测试方法之前调用,包括任何使用 @Before 注释的方法。

因此,如果您将MainActivityComponentActivity 外部的初始化移动到可模拟的地方,那么您将能够在创建主 Activity 之前将其修补在一起。

编辑:

另一种可能的解决方案是根据链接延迟启动活动。

@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();
}
于 2016-01-14T15:41:48.260 回答
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() {
        //...
    }


}
于 2016-10-14T08:16:35.167 回答
0

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

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

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

于 2015-08-04T05:53:15.477 回答