Skip to content

Commit 663327f

Browse files
Use new Coroutines 1.6 Testing APIs
1 parent dde9a84 commit 663327f

File tree

15 files changed

+263
-280
lines changed

15 files changed

+263
-280
lines changed

app/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ android {
5050
dependencies {
5151

5252
def lifecycle_version = "2.2.0"
53-
def coroutines_version = "1.4.2"
53+
def coroutines_version = "1.6.3"
5454

5555
implementation fileTree(dir: 'libs', include: ['*.jar'])
5656
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
@@ -93,6 +93,8 @@ dependencies {
9393
implementation "androidx.room:room-ktx:$room_version"
9494
kapt "androidx.room:room-compiler:$room_version"
9595

96+
testImplementation project(path: ':app')
97+
9698
testImplementation 'junit:junit:4.12'
9799
testImplementation 'androidx.arch.core:core-testing:2.1.0'
98100
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"

app/src/main/java/com/lukaslechner/coroutineusecasesonandroid/playground/channels/2-Offer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ private fun CoroutineScope.generateRandom() = produce {
2828

2929
// emit in flows or send in channels will suspend until someone can receive the item
3030
// send(Random.nextInt())
31-
offer(Random.nextInt())
31+
trySend(Random.nextInt())
3232
}
3333
}

app/src/test/java/com/lukaslechner/coroutineusecasesonandroid/playground/testing/1_testing_coroutines.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package com.lukaslechner.coroutineusecasesonandroid.playground.testing
33
import kotlinx.coroutines.CoroutineScope
44
import kotlinx.coroutines.delay
55
import kotlinx.coroutines.launch
6-
import kotlinx.coroutines.test.runBlockingTest
6+
import kotlinx.coroutines.test.advanceTimeBy
7+
import kotlinx.coroutines.test.currentTime
8+
import kotlinx.coroutines.test.runTest
79
import org.junit.Test
810

911

@@ -25,7 +27,7 @@ fun CoroutineScope.functionThatStartsNewCoroutine() {
2527
class TestClass {
2628

2729
@Test
28-
fun `functionWithDelay should return 42`() = runBlockingTest {
30+
fun `functionWithDelay should return 42`() = runTest {
2931

3032
val realTimeStart = System.currentTimeMillis()
3133
val virtualTimeStart = currentTime

app/src/test/java/com/lukaslechner/coroutineusecasesonandroid/usecases/coroutines/usecase1/FakeSuccessApi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.lukaslechner.coroutineusecasesonandroid.mock.VersionFeatures
66
import com.lukaslechner.coroutineusecasesonandroid.mock.mockAndroidVersions
77
import com.lukaslechner.coroutineusecasesonandroid.utils.EndpointShouldNotBeCalledException
88

9-
class FakeSuccessApi() : MockApi {
9+
class FakeSuccessApi : MockApi {
1010

1111
override suspend fun getRecentAndroidVersions(): List<AndroidVersion> {
1212
return mockAndroidVersions

app/src/test/java/com/lukaslechner/coroutineusecasesonandroid/usecases/coroutines/usecase1/PerformSingleNetworkRequestViewModelTest.kt

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package com.lukaslechner.coroutineusecasesonandroid.usecases.coroutines.usecase1
22

33
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
44
import com.lukaslechner.coroutineusecasesonandroid.mock.mockAndroidVersions
5-
import com.lukaslechner.coroutineusecasesonandroid.utils.MainCoroutineScopeRule
5+
import com.lukaslechner.coroutineusecasesonandroid.utils.ReplaceMainDispatcherRule
66
import kotlinx.coroutines.ExperimentalCoroutinesApi
7-
import kotlinx.coroutines.test.runBlockingTest
7+
import kotlinx.coroutines.test.runTest
88
import org.junit.Assert.assertEquals
99
import org.junit.Assert.assertTrue
1010
import org.junit.Rule
@@ -18,43 +18,38 @@ class PerformSingleNetworkRequestViewModelTest {
1818
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
1919

2020
@get: Rule
21-
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
21+
val replaceMainDispatcherRule = ReplaceMainDispatcherRule()
2222

2323
private val receivedUiStates = mutableListOf<UiState>()
2424

2525
@Test
26-
fun `should return Success when network request is successful`() =
27-
mainCoroutineScopeRule.runBlockingTest {
28-
val fakeApi = FakeSuccessApi()
29-
val viewModel =
30-
PerformSingleNetworkRequestViewModel(fakeApi)
31-
observeViewModel(viewModel)
26+
fun `should return Success when network request is successful`() = runTest {
27+
val fakeApi = FakeSuccessApi()
28+
val viewModel = PerformSingleNetworkRequestViewModel(fakeApi)
29+
observeViewModel(viewModel)
3230

33-
assertTrue(receivedUiStates.isEmpty())
31+
assertTrue(receivedUiStates.isEmpty())
3432

35-
viewModel.performSingleNetworkRequest()
33+
viewModel.performSingleNetworkRequest()
3634

37-
assertEquals(
38-
listOf(
39-
UiState.Loading,
40-
UiState.Success(mockAndroidVersions)
41-
),
42-
receivedUiStates
43-
)
44-
}
35+
assertEquals(
36+
listOf(
37+
UiState.Loading,
38+
UiState.Success(mockAndroidVersions)
39+
),
40+
receivedUiStates
41+
)
42+
}
4543

4644
@Test
47-
fun `should return Error when network request fails`() =
48-
mainCoroutineScopeRule.runBlockingTest {
49-
val fakeApi = FakeErrorApi()
50-
51-
val viewModel =
52-
PerformSingleNetworkRequestViewModel(fakeApi)
53-
observeViewModel(viewModel)
45+
fun `should return Error when network request fails`() = runTest {
46+
val fakeApi = FakeErrorApi()
47+
val viewModel = PerformSingleNetworkRequestViewModel(fakeApi)
48+
observeViewModel(viewModel)
5449

55-
assertTrue(receivedUiStates.isEmpty())
50+
assertTrue(receivedUiStates.isEmpty())
5651

57-
viewModel.performSingleNetworkRequest()
52+
viewModel.performSingleNetworkRequest()
5853

5954
assertEquals(
6055
listOf(

app/src/test/java/com/lukaslechner/coroutineusecasesonandroid/usecases/coroutines/usecase10/CalculationInBackgroundViewModelTest.kt

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,80 @@
11
package com.lukaslechner.coroutineusecasesonandroid.usecases.coroutines.usecase10
22

33
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
4-
import com.lukaslechner.coroutineusecasesonandroid.utils.MainCoroutineScopeRule
5-
import kotlinx.coroutines.test.runBlockingTest
4+
import com.lukaslechner.coroutineusecasesonandroid.utils.ReplaceMainDispatcherRule
5+
import kotlinx.coroutines.ExperimentalCoroutinesApi
6+
import kotlinx.coroutines.test.StandardTestDispatcher
7+
import kotlinx.coroutines.test.runCurrent
8+
import kotlinx.coroutines.test.runTest
69
import org.junit.Assert
710
import org.junit.Rule
811
import org.junit.Test
912
import org.junit.rules.TestRule
1013

14+
@ExperimentalCoroutinesApi
1115
class CalculationInBackgroundViewModelTest {
1216

1317
@get:Rule
1418
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
1519

1620
@get: Rule
17-
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
21+
val replaceMainDispatcherRule = ReplaceMainDispatcherRule()
1822

1923
private val receivedUiStates = mutableListOf<UiState>()
2024

2125
@Test
22-
fun `performCalculation() should perform correct calculations`() =
23-
mainCoroutineScopeRule.runBlockingTest {
24-
val viewModel =
25-
CalculationInBackgroundViewModel(mainCoroutineScopeRule.testDispatcher).apply {
26-
observe()
27-
}
26+
fun `performCalculation() should perform correct calculations`() = runTest {
27+
val viewModel =
28+
CalculationInBackgroundViewModel(StandardTestDispatcher(testScheduler)).apply {
29+
observe()
30+
}
2831

29-
Assert.assertTrue(receivedUiStates.isEmpty())
32+
Assert.assertTrue(receivedUiStates.isEmpty())
3033

31-
viewModel.performCalculation(1)
34+
viewModel.performCalculation(1)
35+
runCurrent()
3236

33-
Assert.assertEquals(
34-
UiState.Loading,
35-
receivedUiStates.first()
36-
)
37+
Assert.assertEquals(
38+
UiState.Loading,
39+
receivedUiStates.first()
40+
)
3741

38-
Assert.assertEquals(
39-
"1",
40-
(receivedUiStates[1] as UiState.Success).result
41-
)
42+
Assert.assertEquals(
43+
"1",
44+
(receivedUiStates[1] as UiState.Success).result
45+
)
4246

43-
receivedUiStates.clear()
47+
receivedUiStates.clear()
4448

45-
viewModel.performCalculation(2)
49+
viewModel.performCalculation(2)
50+
runCurrent()
4651

47-
Assert.assertEquals(
48-
UiState.Loading,
49-
receivedUiStates.first()
50-
)
52+
Assert.assertEquals(
53+
UiState.Loading,
54+
receivedUiStates.first()
55+
)
5156

52-
Assert.assertEquals(
53-
"2",
54-
(receivedUiStates[1] as UiState.Success).result
55-
)
57+
Assert.assertEquals(
58+
"2",
59+
(receivedUiStates[1] as UiState.Success).result
60+
)
5661

57-
receivedUiStates.clear()
62+
receivedUiStates.clear()
5863

59-
viewModel.performCalculation(3)
64+
viewModel.performCalculation(3)
65+
runCurrent()
6066

61-
Assert.assertEquals(
62-
UiState.Loading,
63-
receivedUiStates.first()
64-
)
67+
Assert.assertEquals(
68+
UiState.Loading,
69+
receivedUiStates.first()
70+
)
6571

66-
Assert.assertEquals(
67-
"6",
68-
(receivedUiStates[1] as UiState.Success).result
69-
)
72+
Assert.assertEquals(
73+
"6",
74+
(receivedUiStates[1] as UiState.Success).result
75+
)
7076

71-
}
77+
}
7278

7379
private fun CalculationInBackgroundViewModel.observe() {
7480
uiState().observeForever { uiState ->

app/src/test/java/com/lukaslechner/coroutineusecasesonandroid/usecases/coroutines/usecase12/FactorialCalculatorTest.kt

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,19 @@ package com.lukaslechner.coroutineusecasesonandroid.usecases.coroutines.usecase1
22

33
import junit.framework.Assert.assertEquals
44
import kotlinx.coroutines.ExperimentalCoroutinesApi
5-
import kotlinx.coroutines.test.TestCoroutineDispatcher
6-
import kotlinx.coroutines.test.runBlockingTest
7-
import org.junit.Before
5+
import kotlinx.coroutines.runBlocking
6+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
87
import org.junit.Test
98
import java.math.BigInteger
109

1110
@ExperimentalCoroutinesApi
1211
class FactorialCalculatorTest {
1312

14-
lateinit var factorialCalculator: FactorialCalculator
15-
16-
private val testDispatcher = TestCoroutineDispatcher()
17-
18-
@Before
19-
fun setUp() {
20-
factorialCalculator = FactorialCalculator(testDispatcher)
21-
}
22-
2313
@Test
24-
fun `createSubRangeList() should create correct range lists`() = runBlockingTest {
14+
fun `createSubRangeList() should create correct range lists`() {
15+
val testDispatcher = UnconfinedTestDispatcher()
16+
val factorialCalculator = FactorialCalculator(testDispatcher)
17+
2518
assertEquals(
2619
listOf(
2720
SubRange(1, 3),
@@ -51,7 +44,10 @@ class FactorialCalculatorTest {
5144
}
5245

5346
@Test
54-
fun calculateFactorialOfSubRange() = runBlockingTest {
47+
fun calculateFactorialOfSubRange() = runBlocking {
48+
val testDispatcher = UnconfinedTestDispatcher()
49+
val factorialCalculator = FactorialCalculator(testDispatcher)
50+
5551
assertEquals(
5652
BigInteger.valueOf(6),
5753
factorialCalculator.calculateFactorialOfSubRange(SubRange(1, 3))
@@ -67,7 +63,10 @@ class FactorialCalculatorTest {
6763
}
6864

6965
@Test
70-
fun calculateFactorial() = runBlockingTest {
66+
fun calculateFactorial() = runBlocking {
67+
val testDispatcher = UnconfinedTestDispatcher()
68+
val factorialCalculator = FactorialCalculator(testDispatcher)
69+
7170
assertEquals(
7271
BigInteger.valueOf(3628800),
7372
factorialCalculator.calculateFactorial(10, 3)

0 commit comments

Comments
 (0)