您的位置:首页 > 移动开发 > Android开发

Android 单元测试(junit、mockito、robolectric)

2016-08-16 17:43 477 查看
1、运用JUnit4 进行单元测试

首先在工程的
src
文件夹内创建
test
test/java
文件夹。

打开工程的
build.gradle(Module:app)
文件,添加JUnit4依赖,点击Gradle sync按钮。

build.gradle

dependencies {
testCompile 'junit:junit:4.12'
}


(1)新建被测类:

public class Calculator {

public double sum(double a, double b){
// 假设先返回结果0
return 0;
}
}


(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 , 也可以通过命令行运行测试,在工程目录内输入:

./gradlew test


这时测试因为我写被测类的时候,返回的是0,所以跟期望的值不一样,就会失败。

这时,我们修改下Calculator.java的函数:

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


保存,这时候再运行测试,成功,跟期望值一样。

总结:位于
src/tests
目录下的测试是运行在本地电脑Java虚拟机上的单元测试。


编写测试,实现功能使测试通过,然后再添加更多的测试,这种工作方式使快速迭代成为可能,我们称之为测试驱动开发

2、使用Mockito等mocking框架来mock测试。

Mock:

mock对象就是在调试期间用来作为真实对象的替代品。

mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。

打开工程的
build.gradle(Module:app)
文件,添加Mockito依赖,点击Gradle sync按钮。

build.gradle

dependencies {
// 单元测试
testCompile 'org.mockito:mockito-all:2.0.2-beta'
testCompile 'junit:junit:4.12'
}


关于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节点下,配置下:

 sourceSets {
main {
.....
}

test{
java.srcDirs = [ 'src/test/java']
}
}


其他的用法:参考下官方就行,因为官网是英文的,看不懂的,还可以前往:Mockito 中文文档

3、使用Robolectric

Robolectric 是一个针对于Android SDK 的单元测试框架,使用它可以测试驱动你的Android应用程序的开发。测试用例只需要在JVM基础上就能运行起来。

打开工程的
build.gradle(Module:app)
文件,添加Robolectric依赖,点击Gradle sync按钮。

build.gradle

dependencies {
// 单元测试
testCompile 'org.robolectric:robolectric:3.1-rc1'
testCompile 'org.mockito:mockito-all:2.0.2-beta'
testCompile 'junit:junit:4.12'
}


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。

@RunWith(RobolectricTestRunner.class)
public class WelcomeActivityTest {
@Test
public void clickingLogin_shouldStartLoginActivity() {
WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class);
    activity.findViewById(R.id.btn_login).performClick();
Intent expectedIntent = new Intent(activity, WelcomeActivity.class);
     assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent);
}
}


判断点击后textview 文本变化是否正常等:

@RunWith(RobolectricTestRunner.class)
public class WelcomeActivityTest {

@Test
public void clickLoginButton() throws Exception {
Activity activity = Robolectric.buildActivity(WelcomeActivity.class).create().get();

Button btn_login = (Button) activity.findViewById(R.id.btn_login);
TextView tv_result = (TextView) activity.findViewById(R.id.tv_result);

btn_login.performClick();
String resultsText = tv_result.getText().toString();
assertThat(resultsText, equalTo("Click the login button"));
}
}


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

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


这会创建一个WelcomeActivity,并且已经调用了onCreate()。

(1)检查一些在onCreate()和onResume()之间发生的事件:

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


(2)完整的生命周期:

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


(3)使用intent 来启动activity:

Intent intent = new Intent(Intent.ACTION_VIEW);
Activity activity =
    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();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: