Android 單元測試(junit、mockito、robolectric)


1、運用JUnit4 進行單元測試

首先在工程的 src 文件夾內創建 test 和 test/java 文件夾。 

打開工程的 build.gradle(Module:app)文件,添加JUnit4依賴,點擊Gradle sync按鈕。

build.gradle

1 dependencies {
2     testCompile 'junit:junit:4.12'
3 }

(1)新建被測類:

1 public class Calculator {
2 
3     public double sum(double a, double b){
4         // 假設先返回結果0  
5         return 0;
6     }
7 }

(2)新建測試類:

 
         
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class CalculatorTest {

    private Calculator mCalculator;

    @Before
    public void setUp() throws Exception {
        mCalculator = new Calculator();
    }

    @Test
    public void testSum() throws Exception {
        //斷言:1+1 = 2
        assertEquals(mCalculator.sum(1d, 1d),  2d);
    }
}

這時候 右鍵 - testSum()方法,選擇選擇Run > testRun , 也可以通過命令行運行測試,在工程目錄內輸入:

1 ./gradlew test

這時測試因為我寫被測類的時候,返回的是0,所以跟期望的值不一樣,就會失敗。

這時,我們修改下Calculator.java的函數:

1 public double sum(double a, double b){
2     return a + b;
3 }

保存,這時候再運行測試,成功,跟期望值一樣。

總結:位於src/tests目錄下的測試是運行在本地電腦Java虛擬機上的單元測試。

編寫測試,實現功能使測試通過,然后再添加更多的測試,這種工作方式使快速迭代成為可能,我們稱之為測試驅動開發

 

2、使用Mockito等mocking框架來mock測試。

Mock:

mock對象就是在調試期間用來作為真實對象的替代品。

mock測試就是在測試過程中,對那些不容易構建的對象用一個虛擬對象來代替測試的方法就叫mock測試。

打開工程的 build.gradle(Module:app)文件,添加Mockito依賴,點擊Gradle sync按鈕。

build.gradle

1 dependencies {
2     // 單元測試
3     testCompile 'org.mockito:mockito-all:2.0.2-beta'
4     testCompile 'junit:junit:4.12'
5 }

關於mokito的使用,官網已經給出很詳細了。我這里主要想記錄下主要用到的。對於mvp架構下,測試presenter返回到view的數據,是否正確。

配合mvp模式下,利用本地json,模仿網絡請求,進行模擬數據,查看presenter 處理邏輯是否正確。

public class PresenterTest {

    @Mock
    Repository repository; // 網絡請求
    @Mock
    View view; // view

    PresenterImpl presenter;

    @Before
    public void setUp() throws Exception {
        // 如果有使用到rxjava,可以在這里處理rxjava變成同步執行
        MockitoAnnotations.initMocks(this);

        presenter = new PresenterImpl(view, repository);
    }

    @Test
    public void getOrderList() throws Exception{
        String json = readAssetsJSON("get_list.json").optString("data");
        List<ViewModel> list = JSON.parseArray(json, ViewModel.class);

        when(repository.getList(1)).thenReturn(Observable.just(list));
        presenter.getList(1);

        ArgumentCaptor<ArrayList> captor = ArgumentCaptor.forClass(ArrayList.class);
        verify(presenter.getView()).onGetDataByFinish(captor.capture());

        List<ViewModel> viewModels = captor.getValue();

        assertEquals(list.size(), viewModels.size());
    }
}

 get_list.json 是放到 src/test下的assets 目錄下,這個目錄在:打開工程的 build.gradle(Module:app)文件,android節點下的sourceSets節點下,配置下:

1 sourceSets {
2         main {
3             .....
4         }
5 
6         test {
7             java.srcDirs = [ 'src/test/java']
8         }
9     }

其他的用法:參考下官方就行,因為官網是英文的,看不懂的,還可以前往:Mockito 中文文檔

3、使用Robolectric 

Robolectric 是一個針對於Android SDK 的單元測試框架,使用它可以測試驅動你的Android應用程序的開發。測試用例只需要在JVM基礎上就能運行起來。

打開工程的 build.gradle(Module:app)文件,添加Robolectric依賴,點擊Gradle sync按鈕。

build.gradle

1 dependencies {
2     // 單元測試
3     testCompile 'org.robolectric:robolectric:3.1-rc1'
4     testCompile 'org.mockito:mockito-all:2.0.2-beta'
5     testCompile 'junit:junit:4.12'
6 }

1、創建一個WelcomeActivity, 點擊登錄,跳轉到登錄頁面。

布局文件:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
    android:layout_height="match_parent">  
    
<Button          android:id="@+id/btn_login"
android:text="click the btn"          android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>   </LinearLayout> 

Activity:

public class WelcomeActivity extends Activity {  
    @Override 
    protected void onCreate(Bundle savedInstanceState) {       
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.welcome_activity);  
        final View button = findViewById(R.id.btn_login); 
        button.setOnClickListener(new View.OnClickListener() {  
            @Override 
            public void onClick(View view) { 
                startActivity(new Intent(getContext(), LoginActivity.class));     
           }      
        });
     }
 }

測試的是:當用戶點擊登陸按鈕后,我們啟動了正常的intent。

由於Robolectric只是一個模擬的單元測試框架,LoginActivity並不會真正的啟動,但是我們可以檢查是否准確的發出了WelcomActivity的intent。 

 1 @RunWith(RobolectricTestRunner.class 2 public class WelcomeActivityTest {  
 3     @Test 
 4     public void clickingLogin_shouldStartLoginActivity() { 
 5         WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class);       
 6       activity.findViewById(R.id.btn_login).performClick();  
 7         Intent expectedIntent = new Intent(activity, WelcomeActivity.class);         
 8      assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent);  
 9    } 
10

判斷點擊后textview 文本變化是否正常等:

 1 @RunWith(RobolectricTestRunner.class)
 2 public class WelcomeActivityTest {
 3  
 4   @Test
 5   public void clickLoginButton() throws Exception {
 6     Activity activity = Robolectric.buildActivity(WelcomeActivity.class).create().get();
 7  
 8     Button btn_login = (Button) activity.findViewById(R.id.btn_login);
 9     TextView tv_result = (TextView) activity.findViewById(R.id.tv_result);
10  
11     btn_login.performClick();
12     String resultsText = tv_result.getText().toString();
13     assertThat(resultsText, equalTo("Click the login button"));
14   }
15 }

對於控制activity的生命周期,Robolectric 2.2版本以后增加了控制activity方法:

1 Activity activity = Robolectric.buildActivity(WelcomeActivity.class).create().get();

這會創建一個WelcomeActivity,並且已經調用了onCreate()。

(1)檢查一些在onCreate()和onResume()之間發生的事件:

1 ActivityController controller = 
2           Robolectric.buildActivity(WelcomeActivity.class).create().start(); 
3 Activity activity = controller.get(); 
4 // assert that something hasn't happened 
5 activityController.resume(); 

(2)完整的生命周期:

1 Activity activity = 
2       Robolectric.buildActivity(WelcomeActivity.class).create().start().resume().visible().get(); 

(3)使用intent 來啟動activity:

1 Intent intent = new Intent(Intent.ACTION_VIEW); 
2 Activity activity = 
3     Robolectric.buildActivity(WelcomeActivity.class).withIntent(intent).create().get();

(4)保存狀態:

1 Bundle savedInstanceState = new Bundle(); 
2 savedInstanceState.putExtra("user_age", "18");
3 savedInstanceState.putExtra("user_name", "jay");
4 Activity activity = Robolectric.buildActivity(WelcomeActivity.class).create() 
5        .restoreInstanceState(savedInstanceState).get(); 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM