please help me this when i run all the class test methods together the test fails in a method although this method when i run it alone it succeed
public class RealEstatesListPresenterTest {
RealEstatesListPresenter mRealEstatesListPresenter;
@Mock
private RealEstateListBusiness mRealEstateListBusiness;
@Mock
private RealEstatesListContract.View mRealEstatesView;
@BeforeClass
public static void setUpClass() {
RxAndroidPlugins.setInitMainThreadSchedulerHandler(__ -> Schedulers.trampoline());
}
@Before
public void setupTasksPresenter() {
MockitoAnnotations.initMocks(this);
mRealEstatesListPresenter = new RealEstatesListPresenter(mRealEstatesView);
mRealEstatesListPresenter.setmRealEstateListBusiness(mRealEstateListBusiness);
}
@Test
public void testWhenGetAllRealEstates_ProgressISDisplayed() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onNext(new ArrayList<>());
sub.onComplete();
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).showLoading();
}
@Test
public void testWhenGetAllRealEstatesSuccess_ProgressISHidden() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onNext(new ArrayList<>());
sub.onComplete();
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).hideLoading();
}
@Test
public void testWhenGetAllRealEstatesError_ProgressISHidden() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onError(new Throwable());
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).hideLoading();
}
@AfterClass
public static void tearDownClass() {
RxAndroidPlugins.reset();
}}
when i run all the tests together the first two methods pass but the last one fail (testWhenGetAllRealEstatesError_ProgressISHidden) but when i run it alone it pass.
and this is the presenter code
public class RealEstatesListPresenter implements RealEstatesListContract.Presenter {
private RealEstatesListContract.View mView;
private RealEstateListBusiness mRealEstateListBusiness;
private CompositeDisposable mSubscriptions;
@Inject
public RealEstatesListPresenter(RealEstatesListContract.View view) {
this.mView = view;
mSubscriptions = new CompositeDisposable();
}
@Inject
public void setmRealEstateListBusiness(RealEstateListBusiness mRealEstateListBusiness) {
this.mRealEstateListBusiness = mRealEstateListBusiness;
}
@Inject
public void setupListeners() {
mView.setPresenter(this);
}
@Override
public void unSubscribe() {
mSubscriptions.clear();
}
@Override
public void getAllRealEstates() {
mView.showLoading();
mSubscriptions.add(mRealEstateListBusiness.getAllRealEstates().observeOn(AndroidSchedulers.
mainThread()).subscribeOn(Schedulers.io()).subscribe((realEstatesItems) -> {
mView.hideLoading();
mView.showAllRealEstates(realEstatesItems);
}, throwable -> {
mView.hideLoading();
mView.showErrorMessage(throwable.getMessage());
}));
}
}
i found the problem it is in RX Scheulers This error occurs because the default scheduler returned by AndroidSchedulers.mainThread() is an instance of LooperScheduler and relies on Android dependencies that are not available in JUnit tests.
We can avoid this issue by initializing RxAndroidPlugins with a different Scheduler before the tests are run. You can do this inside of a @BeforeClass so the final class would be like this
public class RealEstatesListPresenterTest {
private RealEstatesListPresenter mRealEstatesListPresenter;
@Mock
private RealEstateListBusiness mRealEstateListBusiness;
@Mock
private RealEstatesListContract.View mRealEstatesView;
@BeforeClass
public static void setUpClass() {
Scheduler immediate = new Scheduler() {
@Override
public Worker createWorker() {
return new ExecutorScheduler.ExecutorWorker(Runnable::run);
}
};
RxJavaPlugins.setInitIoSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitComputationSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitNewThreadSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitSingleSchedulerHandler(scheduler -> immediate);
RxAndroidPlugins.setInitMainThreadSchedulerHandler(scheduler -> immediate); }
@Before
public void setupTasksPresenter() {
MockitoAnnotations.initMocks(this);
mRealEstatesListPresenter = new RealEstatesListPresenter(mRealEstatesView);
mRealEstatesListPresenter.setmRealEstateListBusiness(mRealEstateListBusiness);
}
@Test
public void testWhenGetAllRealEstates_ProgressISDisplayed() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onNext(new ArrayList<>());
sub.onComplete();
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).showLoading();
}
@Test
public void testWhenGetAllRealEstatesSuccess_ProgressISHidden() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onNext(new ArrayList<>());
sub.onComplete();
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).hideLoading();
}
@Test
public void testWhenGetAllRealEstatesError_ProgressISHidden() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onError(new Throwable());
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).hideLoading();
}
@Test
public void testWhenGetAllRealEstatesError_ErrorMessageDisplayed() {
when(mRealEstateListBusiness.getAllRealEstates()).thenReturn(Observable.create(sub -> {
sub.onError(new Throwable(""));
}));
mRealEstatesListPresenter.getAllRealEstates();
verify(mRealEstatesView, times(1)).showErrorMessage("");
}
@After
public void teardown() {
Mockito.reset(mRealEstateListBusiness);
Mockito.reset(mRealEstatesView);
Mockito.validateMockitoUsage();
}
@AfterClass
public static void tearDownClass() {
RxJavaPlugins.reset();
RxAndroidPlugins.reset(); }}
I'm not sure about the code itself But If each test run successfully if your run it only and fails if it's running with other tests
Then a test case may make corruptions for other test case if they are sharing some data, running in the same context or accessing the same db, cache, file or any repository each test case should run successfully with no dependence on other test case
As you're using Mockito, It seems it's the issue of its context you should reset mocked objects on each test case (ie in @Before) Mockito provides a reset method Mockito.reset(mRealEstatesView);
The issue is that mockito counts all the hits on that object across all the test cases, So you should reset it before each test case
You can use Android Test Orchestrator. As you can read here
When using AndroidJUnitRunner version 1.0 or higher, you have access to a tool called Android Test Orchestrator, which allows you to run each of your app's tests within its own invocation of Instrumentation.
To add it to your project:
androidTestUtil "androidx.test:orchestrator:1.2.0"
testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.