如何为 Android 的 API 编写单元测试用例?



我想在开发时为我的代码编写一个单元测试用例,在构建APK之前还需要通过所有单元测试用例。请建议我。

对于编写测试用例,您需要遵循一些架构,如 MVP 或 MVVM,您还需要使用 Junit 和 Mockito 测试框架 在这里你可以找到例子。

这里有一个简单的例子,也许它可以帮助你。在这里,我正在使用改造进行联网

活动

package com.ram.com.mvp_sample;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.ram.com.mvp_sample.modal.RemoteRepository;
import com.ram.com.mvp_sample.modal.Repository;
import com.ram.com.mvp_sample.modal.pojo.Example;
import java.util.List;
/**
* A login screen that offers login via email/password.
*/
public class ImageListActivity extends AppCompatActivity implements Contract.View {

private Contract.Presenter presenter;
private ProgressBar mProgressView;
private RecyclerView imageList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_list);
presenter = new Presenter(this, Repository.getInstance(RemoteRepository.getInstance()));
mProgressView = findViewById(R.id.login_progress);
imageList = findViewById(R.id.image_list);
presenter.getImageList(new AppNetworkStatus(this));
}

@Override
public void showProgressBar(boolean show) {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
}
@Override
public void showImageList(List<Example> example) {
ImageListAdapter adapter = new ImageListAdapter(example);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
imageList.setLayoutManager(layoutManager);
imageList.setAdapter(adapter);
}
@Override
public void showError(Object errorCode) {
Toast.makeText(this, errorCode.toString(), Toast.LENGTH_LONG).show();
}
@Override
public void setPresenter(Contract.Presenter presenter) {
this.presenter = presenter;
}
}
存储库

类:它将与远程存储库交互

package com.ram.com.mvp_sample;
import com.ram.com.mvp_sample.modal.DataSource;
import com.ram.com.mvp_sample.modal.Repository;
import com.ram.com.mvp_sample.modal.pojo.Example;
import java.util.List;
public class Presenter implements Contract.Presenter {
private Contract.View view;
private Repository repository;
public Presenter(Contract.View view, Repository storesRepository) {
this.view = view;
this.repository = storesRepository;
this.view.setPresenter(this);
}
@Override
public void getImageList(NetworkStatus networkStatus) {
view.showProgressBar(true);
repository.getList(networkStatus, new DataSource.OnResponseCallBackListener() {
@Override
public void onSuccess(List<Example> data) {
view.showProgressBar(false);
view.showImageList(data);
}
@Override
public void onError(Object error) {
view.showProgressBar(false);
view.showError(error);
}
});
}
@Override
public void start() {
}
}

远程存储库类:它将直接与此处的 Retrofit 集成

package com.ram.com.mvp_sample.modal;
import com.ram.com.mvp_sample.APIClient;
import com.ram.com.mvp_sample.ApiInterface;
import com.ram.com.mvp_sample.NetworkStatus;
import com.ram.com.mvp_sample.modal.pojo.Example;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class RemoteRepository implements DataSource {
private static RemoteRepository INSTANCE = null;
private RemoteRepository() {
}
public static RemoteRepository getInstance() {
if (INSTANCE == null) {
INSTANCE = new RemoteRepository();
}
return INSTANCE;
}
@Override
public void getList(NetworkStatus networkStats, final OnResponseCallBackListener onResponseCallBackListener) {
ApiInterface apiInterface = APIClient.getClient().create(ApiInterface.class);
Call<List<Example>> call1 = apiInterface.getImageList();
call1.enqueue(new Callback<List<Example>>() {
@Override
public void onResponse(Call<List<Example>> call, Response<List<Example>> response) {
onResponseCallBackListener.onSuccess(response.body());
}
@Override
public void onFailure(Call<List<Example>> call, Throwable t) {
onResponseCallBackListener.onError(t.toString());
}
});
}
}
演示器

类:演示器负责与存储库和视图进行通信

package com.ram.com.mvp_sample;
import com.ram.com.mvp_sample.modal.DataSource;
import com.ram.com.mvp_sample.modal.Repository;
import com.ram.com.mvp_sample.modal.pojo.Example;
import java.util.List;
public class Presenter implements Contract.Presenter {
private Contract.View view;
private Repository repository;
public Presenter(Contract.View view, Repository storesRepository) {
this.view = view;
this.repository = storesRepository;
this.view.setPresenter(this);
}
@Override
public void getImageList(NetworkStatus networkStatus) {
view.showProgressBar(true);
repository.getList(networkStatus, new DataSource.OnResponseCallBackListener() {
@Override
public void onSuccess(List<Example> data) {
view.showProgressBar(false);
view.showImageList(data);
}
@Override
public void onError(Object error) {
view.showProgressBar(false);
view.showError(error);
}
});
}
@Override
public void start() {
}
}

演示器类的测试用例

package com.ram.com.mvp_sample;
import com.ram.com.mvp_sample.modal.DataSource;
import com.ram.com.mvp_sample.modal.Repository;
import com.ram.com.mvp_sample.modal.pojo.Example;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class PresenterTest {
private Presenter presenter;
@Mock
private Repository repository;
@Mock
private Contract.View view;
@Mock
private NetworkStatus networkStatus;
@Captor
private ArgumentCaptor<NetworkStatus> networkStatusArgumentCaptor;
@Captor
private ArgumentCaptor<DataSource.OnResponseCallBackListener> callBackListenerArgumentCaptor;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
presenter = new Presenter(view, repository);
}
// Positive test
@Test
public void getImageList() {
when(networkStatus.isOnline()).thenReturn(true);
presenter.getImageList(networkStatus);
verify(repository).getList(networkStatusArgumentCaptor.capture(), callBackListenerArgumentCaptor.capture());
callBackListenerArgumentCaptor.getValue().onSuccess(ArgumentMatchers.<Example>anyList());
InOrder inOrder = Mockito.inOrder(view);
inOrder.verify(view).showProgressBar(true);
inOrder.verify(view).showProgressBar(false);
inOrder.verify(view).showImageList(ArgumentMatchers.<Example>anyList());
}
// Negative test
@Test
public void getImageListNetworkError() {
when(networkStatus.isOnline()).thenReturn(false);
presenter.getImageList(networkStatus);
verify(repository).getList(networkStatusArgumentCaptor.capture(), callBackListenerArgumentCaptor.capture());
callBackListenerArgumentCaptor.getValue().onError(anyString());
InOrder inOrder = Mockito.inOrder(view);
inOrder.verify(view).showProgressBar(true);
inOrder.verify(view).showProgressBar(false);
inOrder.verify(view).showError(anyString());
}
}

存储库类的测试用例

package com.ram.com.mvp_sample;
import com.ram.com.mvp_sample.modal.DataSource;
import com.ram.com.mvp_sample.modal.RemoteRepository;
import com.ram.com.mvp_sample.modal.Repository;
import com.ram.com.mvp_sample.modal.pojo.Example;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class RepositoryTest {
private Repository repository;
@Mock
private RemoteRepository remoteRepository;
@Mock
private NetworkStatus networkStatus;
@Captor
private ArgumentCaptor<NetworkStatus> networkStatusArgumentCaptor;
@Mock
private DataSource.OnResponseCallBackListener callBackListener;
@Captor
private ArgumentCaptor<DataSource.OnResponseCallBackListener> callBackListenerArgumentCaptor;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
repository = Repository.getInstance(remoteRepository);
}
@Test
public void getImageList() {
when(networkStatus.isOnline()).thenReturn(true);
repository.getList(networkStatus, callBackListener);
verify(remoteRepository).getList(networkStatusArgumentCaptor.capture(), callBackListenerArgumentCaptor.capture());
callBackListenerArgumentCaptor.getValue().onSuccess(ArgumentMatchers.<Example>anyList());
Mockito.verify(callBackListener).onSuccess(ArgumentMatchers.<Example>anyList());
callBackListenerArgumentCaptor.getValue().onError("Some Error");
Mockito.verify(callBackListener).onError("Some Error");
}
}

如果您有任何疑问,请告诉我

我一直在使用Mockito为不完全独立的组件编写单元测试用例。

要开始使用 mockito 在项目中添加以下依赖项

// required if you want to use Mockito for unit tests
testCompile 'org.mockito:mockito-core:2.7.22'
// required if you want to use Mockito for Android tests
androidTestCompile 'org.mockito:mockito-android:2.7.22'

单元测试在单个线程上工作,API 调用发生在某个不同的线程上。因此,您需要模拟来自服务器的响应。为此,您可以使用 mockito。

因此,通常在 api 调用中,您只需要检查来自服务器的响应是否被解析到您的 pojo 中。但是在单元测试中获取服务器响应是不可能的。因此,您需要模拟响应。对于那个嘲笑使用Mockito。

最新更新