Skip to content

Commit eed5f3a

Browse files
committedSep 30, 2017
Using TestScheduler to control time
1 parent ba89ac6 commit eed5f3a

File tree

8 files changed

+121
-16
lines changed

8 files changed

+121
-16
lines changed
 

‎app/src/main/java/com/example/tamaskozmer/kotlinrxexample/di/modules/ApplicationModule.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import com.example.tamaskozmer.kotlinrxexample.CustomApplication
66
import com.example.tamaskozmer.kotlinrxexample.model.persistence.AppDatabase
77
import com.example.tamaskozmer.kotlinrxexample.model.repositories.UserRepository
88
import com.example.tamaskozmer.kotlinrxexample.model.services.UserService
9-
import com.example.tamaskozmer.kotlinrxexample.util.CalendarWrapper
10-
import com.example.tamaskozmer.kotlinrxexample.util.ConnectionHelper
11-
import com.example.tamaskozmer.kotlinrxexample.util.PreferencesHelper
9+
import com.example.tamaskozmer.kotlinrxexample.util.*
1210
import com.google.gson.Gson
1311
import dagger.Module
1412
import dagger.Provides
@@ -65,4 +63,8 @@ class ApplicationModule(val application: CustomApplication) {
6563
@Provides
6664
@Singleton
6765
fun provideCalendarWrapper() = CalendarWrapper()
66+
67+
@Provides
68+
@Singleton
69+
fun provideSchedulerProvider() : SchedulerProvider = AppSchedulerProvider()
6870
}

‎app/src/main/java/com/example/tamaskozmer/kotlinrxexample/di/modules/UserListFragmentModule.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.example.tamaskozmer.kotlinrxexample.di.modules
33
import com.example.tamaskozmer.kotlinrxexample.domain.interactors.GetUsers
44
import com.example.tamaskozmer.kotlinrxexample.model.repositories.UserRepository
55
import com.example.tamaskozmer.kotlinrxexample.presentation.presenters.UserListPresenter
6+
import com.example.tamaskozmer.kotlinrxexample.util.SchedulerProvider
67
import dagger.Module
78
import dagger.Provides
89

@@ -15,5 +16,6 @@ class UserListFragmentModule() {
1516
fun provideGetUsers(userRepository: UserRepository) = GetUsers(userRepository)
1617

1718
@Provides
18-
fun providePresenter(getUsers: GetUsers) = UserListPresenter(getUsers)
19+
fun providePresenter(getUsers: GetUsers, schedulerProvider: SchedulerProvider)
20+
= UserListPresenter(getUsers, schedulerProvider)
1921
}

‎app/src/main/java/com/example/tamaskozmer/kotlinrxexample/presentation/presenters/UserListPresenter.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ package com.example.tamaskozmer.kotlinrxexample.presentation.presenters
33
import com.example.tamaskozmer.kotlinrxexample.domain.interactors.GetUsers
44
import com.example.tamaskozmer.kotlinrxexample.presentation.view.UserListView
55
import com.example.tamaskozmer.kotlinrxexample.presentation.view.viewmodels.UserViewModel
6-
import io.reactivex.android.schedulers.AndroidSchedulers
7-
import io.reactivex.schedulers.Schedulers
6+
import com.example.tamaskozmer.kotlinrxexample.util.SchedulerProvider
87

98
/**
109
* Created by Tamas_Kozmer on 7/4/2017.
1110
*/
1211
class UserListPresenter(
13-
private val getUsers: GetUsers) : BasePresenter<UserListView>() {
12+
private val getUsers: GetUsers,
13+
private val schedulerProvider: SchedulerProvider) : BasePresenter<UserListView>() {
1414

1515
private val offset = 5
1616

@@ -21,8 +21,8 @@ class UserListPresenter(
2121
loading = true
2222
val pageToRequest = if (forced) 1 else page
2323
getUsers.execute(pageToRequest, forced)
24-
.subscribeOn(Schedulers.io())
25-
.observeOn(AndroidSchedulers.mainThread())
24+
.subscribeOn(schedulerProvider.ioScheduler())
25+
.observeOn(schedulerProvider.uiScheduler())
2626
.subscribe(
2727
{ users -> handleSuccess(forced, users) },
2828
{ handleError() })
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.example.tamaskozmer.kotlinrxexample.util
2+
3+
import io.reactivex.Scheduler
4+
import io.reactivex.android.schedulers.AndroidSchedulers
5+
import io.reactivex.schedulers.Schedulers
6+
7+
/**
8+
* Created by Tamas_Kozmer on 8/4/2017.
9+
*/
10+
class AppSchedulerProvider : SchedulerProvider {
11+
12+
override fun ioScheduler() = Schedulers.io()
13+
override fun uiScheduler(): Scheduler = AndroidSchedulers.mainThread()
14+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.example.tamaskozmer.kotlinrxexample.util
2+
3+
import io.reactivex.Scheduler
4+
5+
/**
6+
* Created by Tamas_Kozmer on 8/4/2017.
7+
*/
8+
interface SchedulerProvider {
9+
fun uiScheduler() : Scheduler
10+
fun ioScheduler() : Scheduler
11+
}

‎app/src/test/java/com/example/tamaskozmer/kotlinrxexample/presentation/presenters/UserListPresenterTest.kt

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,26 @@ package com.example.tamaskozmer.kotlinrxexample.presentation.presenters
33
import com.example.tamaskozmer.kotlinrxexample.domain.interactors.GetUsers
44
import com.example.tamaskozmer.kotlinrxexample.presentation.view.UserListView
55
import com.example.tamaskozmer.kotlinrxexample.presentation.view.viewmodels.UserViewModel
6-
import com.example.tamaskozmer.kotlinrxexample.testutil.ImmediateSchedulerRule
6+
import com.example.tamaskozmer.kotlinrxexample.testutil.TestSchedulerProvider
77
import io.reactivex.Single
88
import org.junit.Before
9-
import org.junit.Rule
109
import org.junit.Test
10+
import org.mockito.ArgumentMatchers
1111
import org.mockito.Mock
12+
import org.mockito.Mockito
1213
import org.mockito.Mockito.anyBoolean
1314
import org.mockito.Mockito.anyInt
1415
import org.mockito.Mockito.times
1516
import org.mockito.Mockito.verify
1617
import org.mockito.MockitoAnnotations
18+
import java.util.concurrent.TimeUnit
1719
import org.mockito.Mockito.`when` as whenever
1820

1921
/**
2022
* Created by Tamas_Kozmer on 7/21/2017.
2123
*/
2224
class UserListPresenterTest {
2325

24-
@Rule @JvmField
25-
val immediateSchedulerRule = ImmediateSchedulerRule()
26-
2726
@Mock
2827
lateinit var mockGetUsers: GetUsers
2928

@@ -32,10 +31,13 @@ class UserListPresenterTest {
3231

3332
lateinit var userListPresenter: UserListPresenter
3433

34+
lateinit var testSchedulerProvider: TestSchedulerProvider
35+
3536
@Before
3637
fun setUp() {
3738
MockitoAnnotations.initMocks(this)
38-
userListPresenter = UserListPresenter(mockGetUsers)
39+
testSchedulerProvider = TestSchedulerProvider()
40+
userListPresenter = UserListPresenter(mockGetUsers, testSchedulerProvider)
3941
}
4042

4143
@Test
@@ -53,6 +55,8 @@ class UserListPresenterTest {
5355
userListPresenter.attachView(mockView)
5456
userListPresenter.getUsers()
5557

58+
testSchedulerProvider.testScheduler.triggerActions()
59+
5660
// Then
5761
verify(mockView).hideLoading()
5862
verify(mockView).showEmptyListError()
@@ -73,6 +77,8 @@ class UserListPresenterTest {
7377
userListPresenter.attachView(mockView)
7478
userListPresenter.getUsers()
7579

80+
testSchedulerProvider.testScheduler.triggerActions()
81+
7682
// Then
7783
verify(mockView).clearList()
7884
}
@@ -93,6 +99,8 @@ class UserListPresenterTest {
9399
userListPresenter.getUsers()
94100
userListPresenter.getUsers()
95101

102+
testSchedulerProvider.testScheduler.triggerActions()
103+
96104
// Then
97105
verify(mockView).clearList()
98106
verify(mockView, times(2)).hideLoading()
@@ -115,9 +123,62 @@ class UserListPresenterTest {
115123
userListPresenter.getUsers(forced = true)
116124
userListPresenter.getUsers(forced = true)
117125

126+
testSchedulerProvider.testScheduler.advanceTimeBy(1, TimeUnit.SECONDS)
127+
118128
// Then
119129
verify(mockView, times(2)).clearList()
120130
verify(mockView, times(2)).hideLoading()
121131
verify(mockView, times(2)).addUsersToList(users)
122132
}
133+
134+
@Test
135+
fun testOnScrollChanged_offsetReachedAndLoading_dontRequestNextPage() {
136+
callOnScrollChanged(5, 1)
137+
138+
// Then
139+
verify(mockGetUsers, times(1))
140+
.execute(ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean())
141+
}
142+
143+
@Test
144+
fun testOnScrollChanged_offsetReachedAndNotLoading_requestNextPage() {
145+
callOnScrollChanged(5, 3)
146+
147+
// Then
148+
verify(mockGetUsers, times(2))
149+
.execute(ArgumentMatchers.anyInt(), ArgumentMatchers.anyBoolean())
150+
}
151+
152+
@Test
153+
fun testOnScrollChanged_lastItemReachedAndLoading_showLoading() {
154+
callOnScrollChanged(10, 1)
155+
156+
// Then
157+
verify(mockView).showLoading()
158+
}
159+
160+
private fun callOnScrollChanged(lastVisibleItemPosition: Int, secondsDelay: Long) {
161+
getUsersWithLoadingDelay()
162+
testSchedulerProvider.testScheduler.advanceTimeBy(secondsDelay, TimeUnit.SECONDS)
163+
164+
userListPresenter.onScrollChanged(lastVisibleItemPosition, 10)
165+
}
166+
167+
private fun getUsersWithLoadingDelay() {
168+
// Given
169+
val users = listOf(UserViewModel(1, "Name", 1000, ""))
170+
val single: Single<List<UserViewModel>> = Single.create {
171+
emitter ->
172+
emitter.onSuccess(users)
173+
}
174+
175+
val delayedSingle = single.delay(2, TimeUnit.SECONDS, testSchedulerProvider.testScheduler)
176+
177+
// When
178+
Mockito.`when`(mockGetUsers.execute(anyInt(), anyBoolean())).thenReturn(delayedSingle)
179+
180+
userListPresenter.attachView(mockView)
181+
userListPresenter.getUsers()
182+
}
183+
123184
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.example.tamaskozmer.kotlinrxexample.testutil
2+
3+
import com.example.tamaskozmer.kotlinrxexample.util.SchedulerProvider
4+
import io.reactivex.schedulers.TestScheduler
5+
6+
/**
7+
* Created by Tamas_Kozmer on 9/21/2017.
8+
*/
9+
class TestSchedulerProvider() : SchedulerProvider {
10+
11+
val testScheduler: TestScheduler = TestScheduler()
12+
13+
override fun uiScheduler() = testScheduler
14+
override fun ioScheduler() = testScheduler
15+
}

‎build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ buildscript {
77
jcenter()
88
}
99
dependencies {
10-
classpath 'com.android.tools.build:gradle:3.0.0-beta4'
10+
classpath 'com.android.tools.build:gradle:3.0.0-beta6'
1111
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1212

1313
// NOTE: Do not place your application dependencies here; they belong

0 commit comments

Comments
 (0)