在Robolectric2.2之前氯葬,大多數(shù)測試通過調(diào)用構(gòu)造方法來直接創(chuàng)建activites(new MyActivity()),然后手工調(diào)用生命周期方法比如onCreate()。一些shadowActivity的方法也被廣泛的應用(shadowActivity.callOnCreate())退子。
Robolectric的一個流式API ActivityController改變了這些糟糕的情況具垫,它通過模擬android如何創(chuàng)建activity和通過他們的生命周期驅(qū)動來工作赦颇。ActivityController是一個在2.0推出但是現(xiàn)在需要在2.2使用的流式API啊鸭。除了調(diào)用像onCreate()之外的方法蛇摸,它確保activity的內(nèi)部狀態(tài)和生命周期是相符的急迂。
What do I do now?
我們通常不會直接創(chuàng)建一個ActivityController影所,使用Robolectric.buildActivity()來得到。在你只是簡單的需要一個初始化好的activity的最基本的測試中僚碎,你通澈锩洌可以通過下面的方式來得到:
Activity activity=Robolectric.buildActivity(MyActivity.class).create().get();
這將會創(chuàng)建一個MyActivity的新對象,并且通過生命周期調(diào)用它的onCreate()方法勺阐。
想要驗證在onResume()的時候發(fā)生的事情是在onCreate()之后沒有發(fā)生的卷中?可以用如下方法:
ActivityController controller = Robolectric.buildActivity(MyActivity.class).create().start();
Activity activity =controller.get();
//assert that something hasnt happend
activityController.resume();
//assert it happend!
類似的方法包括start(),pause(),stop(),destroy()。如果你想要測試完整的創(chuàng)建生命周期可以用下面的代碼:
Activity activity = Robolectric.buildActivity(MyActivity.class).create().start().resume.visible().get();
你可以通過intent模擬啟動一個activity
Intent intent = new Intent(Intent.ACTION_VIEW);
Activity activity = Robolectric.buildActivity(MyActivity.class).withIntent(intent).create().get();
或者恢復savedInstanceState
Bundle savedInstanceState=new Bundle();
Activity activity = Robolectric.buildActivity(MyActivity.class).create().restoreInstanceState(savedInstanceState).get();
如果測試中需要更多的方法渊抽,可以參考AcivityController的Java Docs
在上面的使用中有一個visible()方法蟆豫,這個方法的意義是什么?
在真實的android app中懒闷,activity的view層是沒有附著到window上的直到onCreate()被調(diào)用之后十减,在這些發(fā)生之前,activity的view不會被置為visible愤估,這就意味著不能點擊他們嫉称,在真機或者模擬器上activity的onPostResume()被調(diào)用之后才會附著到window上。
所以什么時候去調(diào)用visible()?當你需要在activity進行交互的時候灵疮,比如Robolectric.clickOn()方法需要view是visible狀態(tài)并且功能完備,這種情況就需要在create()之后調(diào)用visible().
使用擴展模塊
為了減少將要測試的應用的外部依賴數(shù)量壳繁,robolectric的shadows被分割成許多擴展包震捣,Robolectric主模塊僅僅提供了為基礎androidsdk提供的shadows,對appcompat或者support library在擴展模塊中提供闹炉,如下表所示:
SDK Package | Robolectric Add-On package |
---|---|
com.android.support.support-v4 | org.robolectric: shadows-support-v4 |
com.android.support.multidex | org.robolectric: shadows-multidex |
com.google.android.gms:play-services | org.robolectric: shadows-play-services |
com.google.android.maps:maps | org.robolectric: shadows-maps |
org.apache.httpcomponents:httpclient | org.robolectric: shadows-httpclient |
Using Library Resources
當Robolectric運行一個test的時候蒿赢,它試圖去下載并且索引應用所有的資源,所以當調(diào)用assetManager的時候可以返回這些資源渣触。對于三方庫提供的資源羡棵,一些擴展性配置就是需要的。
Using Libraries with Gradle
如果你使用gradle構(gòu)建你的項目嗅钻,并且使用 ==RobolectricTestRunner== 來運行你的test皂冰,不需要額外的配置店展,這是因為android的gradle插件將會在構(gòu)建的時候merge三方庫資源和項目的資源文件。RobolectricGradleTestRunner在version3.1過期了秃流。
UsingLibraries with Maven
如果你使用maven來構(gòu)建項目赂蕴,你將需要告訴Robolectric哪里的unpacked 資源是為你使用的哪一個庫準備的,這個配置可以指定在@Config注解里:
@RunWith(RobolectricTestRunner.class)
@Config(libraries={
"build/unpacked-libraries/library1",
"build/unpacked-libraries/library2"
})
public class TestClass{
}
或者在robolectric.properties文件中指定:
libraries=build/unpacked-libraries/library1,build/unpacked-libraries/library2
所有路徑相對于工程的根目錄
Debugging Resource Loading Issues
如果你不能確信一個指定的庫的資源是否已經(jīng)下載完成舶胀,通過設置系統(tǒng)屬性==robolectric.logging.enabled=true== 來打開debug日志然后再運行測試概说。你會看到一些輸出如下:
loading resources for 'com.foo' from build/unpacked-libraries/library1...
如果你看不到一個指定的庫在這個列表中,再次檢查一下配置
Using Qualified Resources(限定資源)
在android developer docs 的描述中嚣伐,資源限定符允許你根據(jù)設備的語言糖赔,屏幕尺寸,是否夜間等因素改變你的資源加載轩端。當你要做出嚴謹?shù)臏y試是乏味的(每個字符串都有所有支持的語言的翻譯)放典,你會發(fā)現(xiàn)你想要在不同的限定環(huán)境來運行測試。
Specifying Resources in Test
指定一個資源限定符很簡單船万,通過在你的測試用例上或者測試類上使用@Config注解簡單的添加想要的限定符刻撒,這取決于你是想要改變你整個文件還是單個測試的的資源限制。
給出如下資源values/strings.xml
<string name="not_overridden">Not Overridden</string>
<string name="overridden">Unqualified value</string>
<string name="overridden_twice">Unqualified value</string>
value-en/strings.xml
<string name="overridden">English qualified value</string>
<string name="overridden_twice">English qualified value</string>
values-en-port/strings.xml
<string name="overridden_twice">English portrait value</string>
下面使用android資源限定規(guī)則的Robolectric測試將會通過
@Test
@Config(qualifiers="en-port")
public void shouldUseEnglishAndPortraitResources(){
final Context context = RuntimeEnvironment.application;
assertThat(context.getString(R.id.not_overridden)).isEqualTo("Not Overridden");
assertThat(context.getString(R.id.overridden)).isEqualTo("English qualified value");
assertThat(context.getString(R.id.overridden_twice)).isEqualTo("English portrait qualified value");
}
多種限定符需要用破折號分割開耿导,在google限定符列表里可以找到對應的限定符