Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing & RxJava2 (AppBuilders 2018)
Search
Sasa Sekulic
April 16, 2018
Programming
3
400
Testing & RxJava2 (AppBuilders 2018)
With RxJava you can write some complex, multithreaded code - and testing it is easy!
Sasa Sekulic
April 16, 2018
Tweet
Share
More Decks by Sasa Sekulic
See All by Sasa Sekulic
Testing & RxJava2 (GrowIT Serbia 2018)
mrsasha
0
57
Management for developers v.2
mrsasha
0
46
Management for developers
mrsasha
1
160
Reactive programming on Android - why and how v2 (CodeMobile 2017)
mrsasha
0
79
Reactive programming on Android - why and how (Droidcon Krakow 2016)
mrsasha
0
240
Reactive programming on Android - why and how (Droidcon UK 2016)
mrsasha
6
510
Recipes in RxJava for Android, v.3
mrsasha
1
240
Recipes in RxJava for Android, v.2
mrsasha
3
1.2k
Recipes in RxJava for Android
mrsasha
7
1.6k
Other Decks in Programming
See All in Programming
go.mod、DockerfileやCI設定に分散しがちなGoのバージョンをまとめて管理する / Go Connect #3
arthur1
10
2.4k
macOS でできる リアルタイム動画像処理
biacco42
8
2.2k
Honoの来た道とこれから
yusukebe
19
3.1k
ECSのサービス間通信 4つの方法を比較する 〜Canary,Blue/Greenも添えて〜
tkikuc
11
2.3k
Realtime API 入門
riofujimon
0
130
Kubernetes for Data Engineers: Building Scalable, Reliable Data Pipelines
sucitw
1
210
offers_20241022_imakiire.pdf
imakurusu
2
370
Outline View in SwiftUI
1024jp
1
240
現場で役立つモデリング 超入門
masuda220
PRO
14
3k
推し活の ハイトラフィックに立ち向かう Railsとアーキテクチャ - Kaigi on Rails 2024
falcon8823
6
2.4k
VR HMDとしてのVision Pro+ゲーム開発について
yasei_no_otoko
0
110
弊社の「意識チョット低いアーキテクチャ」10選
texmeijin
5
24k
Featured
See All Featured
How GitHub (no longer) Works
holman
310
140k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
14
2k
Producing Creativity
orderedlist
PRO
341
39k
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
What's new in Ruby 2.0
geeforr
343
31k
Rails Girls Zürich Keynote
gr2m
93
13k
GitHub's CSS Performance
jonrohan
1030
460k
It's Worth the Effort
3n
183
27k
Music & Morning Musume
bryan
46
6.1k
How STYLIGHT went responsive
nonsquared
95
5.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.7k
Transcript
None
None
test() Observable.just(1) .test() .assertValue(1) val subject = PublishSubject.create<Int>()
val subject = PublishSubject.create<Int>() subject.onNext(1) subject.test() .assertValueCount(1) .assertValue(1)
TestObserver val testObserver = Observable.just(1).test() testObserver.assertValue(1) val subject
= PublishSubject.create<Int>() val testObserver = subject.test() val testObserver = subject.test() subject.onNext(1) testObserver.assertValueCount(1) testObserver.assertValue(1) subject.onNext(2) testObserver.assertValueCount(2) testObserver.assertValues(1, 2)
Observable.just(1) .test() .assertValueCount(1) .assertValue(1) .assertValue({ it == 1 }) .assertNoValues()
.assertValuesOnly(1) Observable.just(1, 2) .test() .assertValueCount(2) .assertValues(1, 2) .assertValueAt(0, 1) .assertValueAt(0) { it == 1 } .assertNever(3)
Observable.just(1) .test() .assertTerminated() .assertComplete() .assertNoErrors() .assertSubscribed() .assertNotComplete() .assertNotTerminated() .assertNotTerminated() .assertEmpty()
.assertError(PaymentException("test")) .assertError(PaymentMethodNotSupportedException::class.java) .assertError({error -> error.cause == PaymentException("test")}) .assertErrorMessage("test")
assertResult() assertSubscribed().assertValues() .assertNoErrors().assertComplete() Observable.just(1, 2).test() .assertResult(1, 2) assertFailure()
assertSubscribed().assertValues() .assertError().assertNotComplete() Observable.error<Int>(RuntimeException("test")).test() .assertFailure(RuntimeException::class.java) .assertFailure(Predicate { it -> it == RuntimeException() }) .assertFailureAndMessage(RuntimeException::class.java, "test")
assertFailure() Observable.error<Int>(RuntimeException("test")) .startWith(Observable.just(1, 2)) .test() .assertFailure(RuntimeException::class.java, 1, 2) .assertFailure(RuntimeException::class.java)
.assertFailure(Predicate { it -> it == RuntimeException() }) .assertFailureAndMessage(RuntimeException::class.java, "test")
val zippedObservable1 = Observable.error<Int>(Throwable("error 1")) val zippedObservable2 = Observable.error<Int>(Throwable("error 2"))
Observable.zip(zippedObservable1, zippedObservable2, BiFunction({first: Observable.zip(zippedObservable1, zippedObservable2, BiFunction({first: Int, second: Int -> first + second})) .test() .assertErrorMessage("error 1") .assertErrorMessage("error 2")
Observable.just(1).test() .await() .await(1, TimeUnit.SECONDS) Observable.just(1).test() .awaitTerminalEvent() Observable.just(1, 2) Observable.just(1, 2)
.delay (2, TimeUnit.SECONDS) .test() .awaitDone(2, TimeUnit.SECONDS) .awaitCount(2, BaseTestConsumer.TestWaitStrategy.SLEEP_1000MS, 2000) .assertTimeout()
Schedulers Observable.just(1) .observeOn(Schedulers.io()) .test() .assertValue(1) Schedulers Schedulers
Schedulers
Schedulers RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() } Observable.just(1) .observeOn(Schedulers.io()) .test() .assertValue(1) Schedulers
Schedulers RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() } RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() } RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() } Schedulers RxAndroidPlugins.reset() RxAndroidPlugins.setInitMainThreadSchedulerHandler {Schedulers.trampoline()}
Schedulers @Rule class TrampolineSchedulerRule : TestRule { override fun apply(base:
Statement, d: Description): Statement { return object : Statement() { @Throws(Throwable::class) override fun evaluate() { RxJavaPlugins.setIoSchedulerHandler… try { base.evaluate() } finally { RxJavaPlugins.reset() } } } } }
Schedulers @Rule @Rule val schedulerRule = TrampolineSchedulerRule() https://medium.com/@fabioCollini/testing-asynchronous-rxjava-code-using-mockito-
8ad831a16877 https://www.infoq.com/articles/Testing-RxJava
Schedulers Schedulers interface SchedulerProvider { fun ui(): Scheduler fun computation():
Scheduler fun io(): Scheduler } class AppSchedulerProvider : SchedulerProvider { override fun ui() = AndroidSchedulers.mainThread() override fun computation() = Schedulers.computation() override fun io() = Schedulers.io() } class TrampolineSchedulerProvider : SchedulerProvider { override fun ui() = Schedulers.trampoline() override fun computation() = Schedulers.trampoline() override fun io() = Schedulers.trampoline() }
Schedulers class UsesSchedulerProvider (schedulers: SchedulerProvider) { … … }
fun methodWithWorker(scheduler: Scheduler): AtomicInteger { val counter = AtomicInteger() val
worker = scheduler.createWorker() worker.schedule({ counter.incrementAndGet() }) worker.schedule({ counter.incrementAndGet() }) return counter } val scheduler = TestScheduler() val counter = methodWithWorker(scheduler) Assert.assertEquals(2, counter.get()) testScheduler.triggerActions() Assert.assertEquals(2, counter.get())
TestScheduler val timedoutObservable = Observable.never<Int>() .timeout(5, TimeUnit.SECONDS) timedoutObservable.test() .assertError(TimeoutException::class.java) timeout()
timeout(5, TimeUnit.SECONDS) == timeout(5, TimeUnit.SECONDS, Schedulers.computation())
TestScheduler val scheduler = TestScheduler() val timedoutObservable = Observable.never<Int>() val
timedoutObservable = Observable.never<Int>() .timeout(5, TimeUnit.SECONDS, ,scheduler) advanceTimeBy() scheduler.advanceTimeBy(5, TimeUnit.SECONDS) timedoutObservable.test() .assertError(TimeoutException::class.java)
TestScheduler TestScheduler val scheduler = TestScheduler(2, TimeUnit.SECONDS) advanceTimeTo() Scheduler.advanceTimeTo(5, TimeUnit.SECONDS)
TestScheduler TestScheduler val currentTime = scheduler.now(TimeUnit.SECONDS)