@@ -37,6 +37,7 @@ import kotlin.test.Test
37
37
import kotlin.test.assertContentEquals
38
38
import kotlin.test.assertEquals
39
39
import kotlin.test.assertNotNull
40
+ import kotlin.test.assertNull
40
41
import kotlin.test.assertTrue
41
42
import kotlin.time.ExperimentalTime
42
43
@@ -286,7 +287,7 @@ class UserRepositoryImplTest {
286
287
val job = launch(start = CoroutineStart .UNDISPATCHED ) {
287
288
repo.getUsers().toList(events)
288
289
}
289
- delay(1_000 )
290
+ delay(5_000 )
290
291
job.cancel()
291
292
292
293
assertEquals(1 , events.size)
@@ -302,6 +303,67 @@ class UserRepositoryImplTest {
302
303
}
303
304
}
304
305
}
306
+
307
+ @Test
308
+ fun test_getUsers_withApiCallError_rethrows () = testDispatcher.runBlockingTest {
309
+ coEvery { userApiService.getUsers() } throws IOException ()
310
+ every { errorMapper(ofType<IOException >()) } returns UserError .NetworkError
311
+
312
+ val events = mutableListOf<Either <UserError , List <User >>>()
313
+ val job = launch(start = CoroutineStart .UNDISPATCHED ) {
314
+ repo.getUsers().toList(events)
315
+ }
316
+ delay(20_000 )
317
+ job.cancel()
318
+
319
+ assertEquals(1 , events.size)
320
+ val result = events.single()
321
+ assertTrue(result.isLeft())
322
+ assertNull(result.orNull())
323
+ assertEquals(UserError .NetworkError , result.leftOrThrow)
324
+
325
+ coVerify(exactly = 3 ) { userApiService.getUsers() } // retry 3 times.
326
+ verify(exactly = 1 ) { errorMapper(ofType<IOException >()) }
327
+ }
328
+
329
+ @Test
330
+ fun test_getUsers_withApiCallSuccess_emitsInitialAndUpdatedUsers () =
331
+ testDispatcher.runBlockingTest {
332
+ val user = USERS .last()
333
+ val userResponse = USER_RESPONSES .last()
334
+ coEvery { userApiService.getUsers() } returns USER_RESPONSES .dropLast(1 )
335
+ coEvery { userApiService.add(USER_BODY ) } returns userResponse
336
+ coEvery { userApiService.remove(user.id) } returns userResponse
337
+ every { domainToBody(user) } returns USER_BODY
338
+ USER_RESPONSES .zip(USERS ).forEach { (r, u) -> every { responseToDomain(r) } returns u }
339
+
340
+ val events = mutableListOf<Either <UserError , List <User >>>()
341
+ val job = launch(start = CoroutineStart .UNDISPATCHED ) {
342
+ repo.getUsers().toList(events)
343
+ }
344
+ repo.add(user)
345
+ repo.remove(user)
346
+ delay(120_000 )
347
+ job.cancel()
348
+
349
+ assertContentEquals(
350
+ events.map { it.getOrThrow },
351
+ listOf (
352
+ USERS .dropLast(1 ),
353
+ USERS ,
354
+ USERS .dropLast(1 ),
355
+ )
356
+ )
357
+
358
+ coVerify { userApiService.getUsers() }
359
+ coVerify { userApiService.add(USER_BODY ) }
360
+ coVerify { userApiService.remove(user.id) }
361
+ verify { domainToBody(user) }
362
+ verifySequence {
363
+ USER_RESPONSES .forEach { responseToDomain(it) }
364
+ responseToDomain(USER_RESPONSES .last())
365
+ }
366
+ }
305
367
}
306
368
307
369
private inline val <L , R > Either <L , R >.leftOrThrow: L
0 commit comments