Android 单元测试运行所有类测试都失败,但每个方法都成功运行



当我一起运行所有类测试方法时,请帮助我,测试在方法中失败,尽管当我单独运行此方法时它成功了

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();
}}

当我一起运行所有测试时,前两个方法通过,但最后一个方法失败(testWhenGetAllRealEstatesError_ProgressISHidden(,但是当我单独运行它时,它通过了。

这是演示者代码

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());
    }));
}

}

我发现问题出在RX Scheulers中发生此错误的原因是 AndroidSchedulers.mainThread(( 返回的默认调度程序是 LooperScheduler 的实例,并且依赖于 JUnit 测试中不可用的 Android 依赖项。

我们可以通过在运行测试之前使用不同的调度程序初始化 RxAndroidPlugins 来避免此问题。你可以在@BeforeClass内执行此操作,所以最终的课程将是这样的

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();    }}
您可以使用

Android Test Orchestrator。正如你可以在这里读到的

使用 AndroidJUnitRunner 1.0 或更高版本时,你可以访问名为 Android Test Orchestrator 的工具,该工具允许您在应用自己的检测调用中运行应用的每个测试。

要将其添加到项目中,请执行以下操作:

  • 将依赖项添加到 build.gradle (:app( 文件:

androidTestUtil "androidx.test:orchestrator:1.2.0"

  • 将以下代码添加到测试选项:

testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' }

我不确定代码本身但是,如果每个测试都成功运行,如果您只运行它如果与其他测试一起运行,则失败

然后,如果测试用例共享某些数据,在同一上下文中运行或访问相同的数据库,缓存,文件或任何存储库,则测试用例可能会损坏其他测试用例每个测试用例都应成功运行,不依赖于其他测试用例

当您使用Mockito时,似乎这是其上下文的问题您应该在每个测试用例上重置模拟对象(即在 @Before 中(Mockito提供了一种重置方法Mockito.reset(mRealEstatesView(;

问题是 mockito 会计算所有测试用例中对该对象的所有命中,因此您应该在每个测试用例之前重置它

相关内容

  • 没有找到相关文章

最新更新