12

我正在嘗試使用Mockito測試活動& Dagger。我已經能夠在我的應用程序中向Activity中注入依賴項,但在測試Activity時,我無法將注入模擬注入到Activity中。我應該注入Activity來測試還是讓getActivity()創建它?使用Dagger進行Android功能測試

public class MainActivityTest extends 
    ActivityInstrumentationTestCase2<MainActivity> { 

@Inject Engine engineMock; 
private MainActivity mActivity; 
private Button mLogoutBtn; 


public MainActivityTest() { 
    super(MainActivity.class); 
} 

@Override 
protected void setUp() throws Exception { 
    super.setUp(); 

    // Inject engineMock to test 
    ObjectGraph.create(new TestModule()).inject(this); 
} 

@Override 
protected void tearDown() { 
    if (mActivity != null) 
     mActivity.finish(); 
} 

@Module(
includes = MainModule.class, 
entryPoints = MainActivityTest.class, 
overrides = true 
) 

static class TestModule { 
    @Provides 
    @Singleton 
    Engine provideEngine() { 
     return mock(Engine.class); 
    } 
} 

@UiThreadTest 
public void testLogoutButton() { 

    when(engineMock.isLoggedIn()).thenReturn(true); 

    mActivity = getActivity(); 
    mLogoutBtn = (Button) mActivity.findViewById(R.id.logoutButton); 

    // how to inject engineMock to Activity under test? 
    ObjectGraph.create(new TestModule()).inject(this.mActivity); 

    assertTrue(mLogoutBtn.isEnabled() == true); 
} 
} 

回答

1

我做了一些更多的實驗,發現Dagger在注入測試時無法正確創建活動。在新版本的測試中,testDoSomethingCalledOnEngine通過,但OnCreate未在MainActivity上調用。第二個測試testDoSomethingUI失敗,實際上有兩個MainActivity實例,onCreate被調用到另一個實例(由ActivityInstrumentationTestCase2創建),但不是另一個。也許Square的開發人員只考慮用Robolectric而不是Android儀器測試來測試Activites?

public class MainActivityTest extends 
    ActivityInstrumentationTestCase2<MainActivity> { 

@Inject Engine engineMock; 
@Inject MainActivity mActivity; 

public MainActivityTest() { 
    super(MainActivity.class); 
} 

@Override 
protected void setUp() throws Exception { 
    super.setUp(); 

    // Inject engineMock to test & Activity under test 
    ObjectGraph.create(new TestModule()).inject(this); 
} 


@Module(
includes = MainModule.class, 
entryPoints = MainActivityTest.class, 
overrides = true 
) 

static class TestModule { 
    @Provides 
    @Singleton 
    Engine provideEngine() { 
     return mock(Engine.class); 
    } 
} 

public void testDoSomethingCalledOnEngine() { 
    when(engineMock.isLoggedIn()).thenReturn(true); 
    mActivity.onSomethingHappened(); 
    verify(engineMock).doSomething(); 
} 

@UiThreadTest 
public void testDoSomethingUI() { 
    when(engineMock.isLoggedIn()).thenReturn(true); 
    mActivity.onSomethingHappened(); 
    Button btn = (Button) mActivity.findViewById(R.id.logoutButton); 
    String btnText = btn.getText().toString(); 
    assertTrue(btnText.equals("Log out")); 
} 

}

+3

我們的活動注入自己的onCreate(基類)。我們使用應用程序類的開發版本添加僅限dev模塊到對象圖中。 – 2013-05-10 01:30:17

+5

@JakeWharton你可以指出一個例子,你有Dagger注入模擬UI測試嗎?我從你創建的一些插件知道,你已經和Espresso一起工作過。一個例子,你如何實現測試嘲笑的咖啡測試,將是非常寶貴的! – 2014-04-23 02:10:06

6

我用和的Mockito匕首功能測試。 關鍵概念是您的測試類繼承自ActivityUnitTestCase,而不是ActivityInstrumentationTestCase2;後者超類調用Activity的生命週期方法onStart()來阻止你注入你的測試雙擊依賴項,但是用第一個超類可以處理生命週期更加細化。

您可以看到使用匕首1.0.0和對的Mockito測試活動我的工作實例和片段中:

https://github.com/IIIRepublica/android-civicrm-test

下測試該項目是:

https://github.com/IIIRepublica/android-civicrm

希望這可以幫助你