[JAVA] How to unit test with JVM with source using RxAndroid

phenomenon

If you make it normally, you will get ExceptionInitializerError in the part of ```AndroidSchedulers.mainThread ()` ``.

Why an error

This is because the scheduler returned by ```AndroidSchedulers.mainThread ()` `` depends on Android. (If you depend on Android and do nothing, you need to run it with Android Test using an emulator.) This link to the relevant source I will.

Solution

You can work around this issue by simply initializing it as a separate Scheduler with the RxAndroidPlugins mechanism before the test is run.

Specific source

Below is the source of kotlin. Simply use the Plugin mechanism to define a TestRule that just makes the Scheduler to be used independent of Android.

RxImmediateSchedulerRule.kt


class RxImmediateSchedulerRule : TestRule {

    private val immediate = object : Scheduler() {
        override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
            return super.scheduleDirect(run, 0, unit)
        }

        override fun createWorker(): Worker {
            return ExecutorScheduler.ExecutorWorker { it.run() }
        }
    }

    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            @Throws(Throwable::class)
            override fun evaluate() {
                RxJavaPlugins.setInitIoSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitComputationSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitNewThreadSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitSingleSchedulerHandler({ _ -> immediate })
                RxAndroidPlugins.setInitMainThreadSchedulerHandler({ _ -> immediate })

                try {
                    base.evaluate()
                } finally {
                    RxJavaPlugins.reset()
                    RxAndroidPlugins.reset()
                }
            }
        }
    }
}

And just do this before testing. By the way, please refer to this article for the reason why you do not use @ ClassRule.

@RunWith(PowerMockRunner::class)
@PrepareForTest(Auth::class)
class LoginViewModelTest {

    @Rule
    val schedulers: RxImmediateSchedulerRule = RxImmediateSchedulerRule()

//    companion object {
//        @JvmField
//        @ClassRule
//        val schedulers: RxImmediateSchedulerRule = RxImmediateSchedulerRule()
//    }
    @Test
    fun onClickLogin() {

        val mockAuth = PowerMockito.mock(Auth::class.java)

        val target = LoginViewModel(mockAuth)

        target.mail.set("email")
        target.password.set("password")

        val result = Single.just(AuthEntity().apply {
            accessToken = "123456"
            userId = 100
        })
        PowerMockito.`when`(mockAuth.login("email", "password")).thenReturn(result)

        target.onClickLogin().run()

        Mockito.verify(mockAuth).login("email", "password")
    }
}

Recommended Posts

How to unit test with JVM with source using RxAndroid
How to dynamically write iterative test cases using test / unit (Test :: Unit)
How to unit test Spring AOP
How to test private scope with JUnit
[Java] How to test for null with JUnit
How to test interrupts during Thread.sleep with JUnit
How to write test code with Basic authentication
Unit test with Junit.
How to write a unit test for Spring Boot 2
Introduction to Micronaut 2 ~ Unit test ~
Unit test architecture using ArchUnit
How to number (number) with html.erb
How to update with activerecord-import
How to authorize using graphql-ruby
How to test including images when using ActiveStorage and Faker
How to set environment variables when using Payjp with Rails
How to decompile apk file to java source code with MAC
How to run only specific files with gem's rake test
How to test a private method with RSpec for yourself
How to make an app using Tensorflow with Android Studio
How to erase test image after running Rspec test with CarrierWave
How to get started with JDBC using PostgresSQL on MacOS
How to register as a customer with Square using Tomcat
How to scroll horizontally with ScrollView
How to get started with slim
How to enclose any character with "~"
How to use mssql-tools with alpine
Sample code to unit test a Spring Boot controller with MockMvc
How to get along with Rails
How to implement UI automated test using image comparison in Selenium
I tested how to use Ruby's test / unit and rock-paper-scissors code.
[RSpec] How to write test code
[RSpec] Unit test (using gem: factory_bot)
Let's unit test with [rails] Rspec!
How to build CloudStack using Docker
How to start Camunda with Docker
How to deploy to AWS using NUXTJS official S3 and CloudFront? With docker-compose
How to realize hybrid search using morphological analysis and Ngram with Solr
How to test private methods with arrays or variadic arguments in JUnit
How to set different source / target versions for production code and test code
How to execute a contract using web3j
How to sort a List using Comparator
How to adjustTextPosition with iOS Keyboard Extension
How to share files with Docker Toolbox
How to compile Java with VsCode & Ant
[Rails] How to upload images using Carrierwave
[Java] How to compare with equals method
How to filter JUnit Test in Gradle
[Android] How to deal with dark themes
How to use BootStrap with Play Framework
[Rails] How to use rails console with docker
Java Artery-Easy to use unit test library
How to switch thumbnail images with JavaScript
[Java] How to calculate age using LocalDate
[Note] How to get started with Rspec
I want to write a unit test!
How to do API-based control with cancancan
How to achieve file download with Feign
How to update related models with accepts_nested_attributes_for
How to set JAVA_HOME with Maven appassembler-maven-plugin
How to implement TextInputLayout with validation function