简体   繁体   English

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

[英]Android Unit testing run all class tests fail but every single method run successfully

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.当我一起运行所有测试时,前两种方法通过但最后一种失败(testWhenGetAllRealEstatesError_ProgressISHidden)但是当我单独运行它时它通过。

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

We can avoid this issue by initializing RxAndroidPlugins with a different Scheduler before the tests are run.我们可以通过在运行测试之前使用不同的调度程序初始化 RxAndroidPlugins 来避免这个问题。 You can do this inside of a @BeforeClass so the final class would be like this您可以在 @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();    }}

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);当您使用 Mockito 时,似乎是上下文的问题,您应该在每个测试用例上重置模拟对象(即在 @Before 中) Mockito 提供了一个重置​​方法 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问题是 mockito 在所有测试用例中计算该对象上的所有命中,所以你应该在每个测试用例之前重置它

You can use Android Test Orchestrator.您可以使用 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.使用 AndroidJUnitRunner 1.0 或更高版本时,您可以访问一个名为 Android Test Orchestrator 的工具,该工具允许您在自己的 Instrumentation 调用中运行应用程序的每个测试。

To add it to your project:要将其添加到您的项目中:

  • add dependency to build.gradle (:app) file:向 build.gradle (:app) 文件添加依赖项:

androidTestUtil "androidx.test:orchestrator:1.2.0"

  • add following code to your testoptions:将以下代码添加到您的测试选项中:

testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM