- Presenter层未使用Android相关API,无需引入Robolectric
- 引入PowerMock,介入私有方法mock
- AndroidSchedulers.mainThread需要通过Rule规则挂钩子Hook住相关API
- View层为接口持有,通过普通Mockito验证
- 需将一个方法的多个分支拆分成多个Test方法,保证每个Test的使用新的Mock实例防止结果互相干扰
AndroidSchedulers.mainThread Hook相关Rule规则
RxSchedulersOverrideRule.java
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import rx.Scheduler;
import rx.android.plugins.RxAndroidPlugins;
import rx.android.plugins.RxAndroidSchedulersHook;
import rx.functions.Func1;
import rx.plugins.RxJavaHooks;
import rx.schedulers.Schedulers;
public class RxSchedulersOverrideRule implements TestRule {
private final RxAndroidSchedulersHook mRxAndroidSchedulersHook = new RxAndroidSchedulersHook() {
@Override
public Scheduler getMainThreadScheduler() {
return Schedulers.immediate();
}
};
private final Func1<Scheduler, Scheduler> mRxJavaImmediateScheduler =
new Func1<Scheduler, Scheduler>() {
@Override
public Scheduler call(Scheduler scheduler) {
return Schedulers.immediate();
}
};
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
RxAndroidPlugins.getInstance().reset();
RxAndroidPlugins.getInstance().registerSchedulersHook(mRxAndroidSchedulersHook);
RxJavaHooks.reset();
RxJavaHooks.setOnIOScheduler(mRxJavaImmediateScheduler);
RxJavaHooks.setOnNewThreadScheduler(mRxJavaImmediateScheduler);
base.evaluate();
RxAndroidPlugins.getInstance().reset();
RxJavaHooks.reset();
}
};
}
}
测试类引入Rule规则
@Rule
public final RxSchedulersOverrideRule mOverrideSchedulersRule = new RxSchedulersOverrideRule();
代码Sample
package com.nd.sdp.live.core.list.presenter;
import com.nd.sdp.live.RxSchedulersOverrideRule;
import com.nd.sdp.live.core.TestException;
import com.nd.sdp.live.core.list.model.VideoBroadcastList;
import com.nd.sdp.live.core.play.entity.VideoLiveBroadcast;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.membermodification.MemberMatcher;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import rx.Observable;
import rx.android.plugins.RxAndroidPlugins;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* 实现层测试
* Created by Young on 2017/4/19.
*/
@PrepareForTest({LiveListPresenterImpl.class})
@RunWith(PowerMockRunner.class)
public class LiveListPresenterImplTest {
private ILiveListPresenter mLiveListPresenter;
private ILiveListPresenter.View mView;
@Rule
public final RxSchedulersOverrideRule mOverrideSchedulersRule = new RxSchedulersOverrideRule();
@Before
public void setUp() throws Exception {
mView = mock(ILiveListPresenter.View.class);
LiveListPresenterImpl liveListPresenter = new LiveListPresenterImpl(mView);
mLiveListPresenter = PowerMockito.spy(liveListPresenter);
}
@Test
public void getBroadcastList() throws Exception {
// With full Data
VideoBroadcastList result = new VideoBroadcastList();
result.items = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.items.add(new VideoLiveBroadcast());
}
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(0)
.thenReturn(Observable.just(result));
mLiveListPresenter.getBroadcastList();
verify(mView, never()).setNoMoreData();
verify(mView).setRefreshing();
verify(mView).refreshComplete();
}
@Test
public void testGetBroadCastWithNoMoreData() throws Exception {
VideoBroadcastList result = new VideoBroadcastList();
result.items = new ArrayList<>();
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(0)
.thenReturn(Observable.just(result));
mLiveListPresenter.getBroadcastList();
verify(mView).setRefreshing();
verify(mView).setNoMoreData();
verify(mView).refreshComplete();
}
@Test
public void testGetBroadCastWithException() throws Exception {
// Exception
Throwable throwable = new TestException();
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(0)
.thenReturn(Observable.error(throwable));
mLiveListPresenter.getBroadcastList();
verify(mView).error(throwable);
verify(mView).setNoMoreData();
verify(mView).refreshComplete();
}
@Test
public void getMoreBroadcast() throws Exception {
// With full Data
VideoBroadcastList result = new VideoBroadcastList();
result.items = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.items.add(new VideoLiveBroadcast());
}
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(anyInt())
.thenReturn(Observable.just(result));
mLiveListPresenter.getMoreBroadcast(1);
verify(mView, never()).setNoMoreData();
verify(mView).addListData(anyListOf(VideoLiveBroadcast.class));
}
@Test
public void getMoreBraodCastWithNoMoreData() throws Exception {
VideoBroadcastList result = new VideoBroadcastList();
result.items = new ArrayList<>();
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(anyInt())
.thenReturn(Observable.just(result));
mLiveListPresenter.getMoreBroadcast(1);
verify(mView).setNoMoreData();
}
@Test
public void getMoreBroadCastWithException() throws Exception {
Throwable throwable = new TestException();
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(Matchers.anyInt())
.thenReturn(Observable.error(throwable));
mLiveListPresenter.getMoreBroadcast(1);
verify(mView).error(throwable);
verify(mView).setNoMoreData();
}
@Test
public void onDestroy() throws Exception {
VideoBroadcastList result = new VideoBroadcastList();
result.items = new ArrayList<>();
for (int i = 0; i < 10; i++) {
result.items.add(new VideoLiveBroadcast());
}
PowerMockito.when(mLiveListPresenter, MemberMatcher.method(LiveListPresenterImpl.class, "getListData", int.class))
.withArguments(anyInt())
.thenReturn(Observable.just(result));
mLiveListPresenter.getBroadcastList();
mLiveListPresenter.getMoreBroadcast(1);
mLiveListPresenter.getBroadcastList();
mLiveListPresenter.onDestroy();
}
@After
public void tearDown() throws Exception {
RxAndroidPlugins.getInstance().reset();
}
}