{"action":"created","issue":{"url":"https://api.github.com/repos/ReactiveX/RxJava/issues/3914","repository_url":"https://api.github.com/repos/ReactiveX/RxJava","labels_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/3914/labels{/name}","comments_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/3914/comments","events_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/3914/events","html_url":"https://github.com/ReactiveX/RxJava/issues/3914","id":153308404,"number":3914,"title":"How to replace TestScheduler in RxJavaSchedulersHook?","user":{"login":"DavidMihola","id":594955,"avatar_url":"https://avatars.githubusercontent.com/u/594955?v=3","gravatar_id":"","url":"https://api.github.com/users/DavidMihola","html_url":"https://github.com/DavidMihola","followers_url":"https://api.github.com/users/DavidMihola/followers","following_url":"https://api.github.com/users/DavidMihola/following{/other_user}","gists_url":"https://api.github.com/users/DavidMihola/gists{/gist_id}","starred_url":"https://api.github.com/users/DavidMihola/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DavidMihola/subscriptions","organizations_url":"https://api.github.com/users/DavidMihola/orgs","repos_url":"https://api.github.com/users/DavidMihola/repos","events_url":"https://api.github.com/users/DavidMihola/events{/privacy}","received_events_url":"https://api.github.com/users/DavidMihola/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-05T19:40:57Z","updated_at":"2016-05-05T19:47:16Z","closed_at":null,"body":"So, I am currently trying to test some time sensitive code in my Android app:\r\n\r\n* Inside my `MainPresenter` I use `interval()` and `delay()` to do a countdown and display text in the `View` accordingly. Both, by default, use `Schedulers.computation()`.\r\n* For testing, I'd like to use a `TestScheduler` so that I am able to forward the time and check if the the correct methods are called on a mock of the `View`.\r\n* Therefore I am using `RxJavaPlugins` and `RxJavaSchedulersHook` to override the `computation` Scheduler to use my `TestScheduler` instead. I also keep a reference to the latter in my test class and use that in each unit test.\r\n\r\nSee this code, which *almost* works:\r\n\r\n```java\r\npublic class MainPresenterTest {\r\n\r\n    private TestScheduler testScheduler;\r\n\r\n    @Before\r\n    public void setupSchedulers() {\r\n        testScheduler = new TestScheduler();\r\n\r\n        RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook() {\r\n            @Override\r\n            public Scheduler getComputationScheduler() {\r\n                return testScheduler;\r\n            }\r\n\r\n            @Override\r\n            public Scheduler getIOScheduler() {\r\n                return testScheduler;\r\n            }\r\n\r\n            @Override\r\n            public Scheduler getNewThreadScheduler() {\r\n                return testScheduler;\r\n            }\r\n        });\r\n\r\n        RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {\r\n\r\n            @Override\r\n            public Scheduler getMainThreadScheduler() {\r\n                return Schedulers.immediate();\r\n            }\r\n        });\r\n    }\r\n\r\n    @Test\r\n    public void nothingHappensInTheFirstThreeSeconds() {\r\n        MainPresenter.View mockedMainPresenterView = mock(MainPresenter.View.class);\r\n        MainPresenter mainPresenter = new MainPresenter(mockedMainPresenterView);\r\n\r\n        mainPresenter.onResume();\r\n\r\n        verifyZeroInteractions(mockedMainPresenterView);\r\n\r\n        testScheduler.advanceTimeTo(2_999, TimeUnit.MILLISECONDS);\r\n\r\n        verifyZeroInteractions(mockedMainPresenterView);\r\n    }\r\n\r\n    @Test\r\n    public void theWholeSequenceCompletesAfterEightSeconds() {\r\n        MainPresenter.View mockedMainPresenterView = mock(MainPresenter.View.class);\r\n        MainPresenter mainPresenter = new MainPresenter(mockedMainPresenterView);\r\n\r\n        mainPresenter.onResume();\r\n\r\n        verifyZeroInteractions(mockedMainPresenterView);\r\n\r\n        testScheduler.advanceTimeTo(8, TimeUnit.SECONDS);\r\n\r\n        verify(mockedMainPresenterView).displayText(\"5\");\r\n        verify(mockedMainPresenterView).displayText(\"4\");\r\n        verify(mockedMainPresenterView).displayText(\"3\");\r\n        verify(mockedMainPresenterView).displayText(\"2\");\r\n        verify(mockedMainPresenterView).displayText(\"1\");\r\n        verify(mockedMainPresenterView).displayText(\"Hello World!\");\r\n\r\n        verifyNoMoreInteractions(mockedMainPresenterView);\r\n    }\r\n```\r\n\r\nActually, it works fine as long as there is only one test case. If I add another one, I get the following exception when `@Before` is running for the second time:\r\n\r\n```\r\njava.lang.IllegalStateException: Another strategy was already registered: ...\r\n```\r\n\r\nI have now done some research and found several candidates for a solution:\r\n* [Create a custom RobolectricGradleTestRunner](http://fedepaol.github.io/blog/2015/09/13/testing-rxjava-observables-subscriptions/)\r\n* [Use `RxJavaPlugins.getInstance().reset();` and a custom `TestRule`](http://alexismas.com/blog/2015/05/20/unit-testing-rxjava/). See also [this discussion about making `reset()` public](https://github.com/ReactiveX/RxJava/issues/2297)\r\n* @JakeWharton, in [the release notes of RxAndroid 1.2.0](https://github.com/ReactiveX/RxAndroid/releases/tag/1.2.0) mentioned:\r\n\r\n> If you were relying on the ability to change the main thread scheduler over time (such as for tests), return a delegating scheduler from the hook which allows changing the delegate instance at will.\r\n\r\nI am assuming this method would also work for any other RxJava scheduler - if I knew how to do it.\r\n\r\nSo, which of these (or any other) methods is preferred for resetting/changing the `TestScheduler` that's used for overriding `Schedulers.computation()` in between tests? In particular, how would the third alternative work exactly? How would that \"delegating scheduler\" look or work?\r\n\r\nThanks for any advice!"},"comment":{"url":"https://api.github.com/repos/ReactiveX/RxJava/issues/comments/217257097","html_url":"https://github.com/ReactiveX/RxJava/issues/3914#issuecomment-217257097","issue_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/3914","id":217257097,"user":{"login":"akarnokd","id":1269832,"avatar_url":"https://avatars.githubusercontent.com/u/1269832?v=3","gravatar_id":"","url":"https://api.github.com/users/akarnokd","html_url":"https://github.com/akarnokd","followers_url":"https://api.github.com/users/akarnokd/followers","following_url":"https://api.github.com/users/akarnokd/following{/other_user}","gists_url":"https://api.github.com/users/akarnokd/gists{/gist_id}","starred_url":"https://api.github.com/users/akarnokd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akarnokd/subscriptions","organizations_url":"https://api.github.com/users/akarnokd/orgs","repos_url":"https://api.github.com/users/akarnokd/repos","events_url":"https://api.github.com/users/akarnokd/events{/privacy}","received_events_url":"https://api.github.com/users/akarnokd/received_events","type":"User","site_admin":false},"created_at":"2016-05-05T19:47:16Z","updated_at":"2016-05-05T19:47:16Z","body":"You should be able now to reset the plugins."}}