-
Notifications
You must be signed in to change notification settings - Fork 0
Async Testing β When to use blocking tests
Devrath edited this page Oct 25, 2023
·
3 revisions
- Sometimes you have a scenario when you have a
suspend
function in the production code. - This suspend function has two parallel co-routines that spawn independently.
- The enclosing suspend function waits for the two of them to complete, Only then the result is returned.
- Here we can use the
runBlockingWay
UserApi.kt
interface UserApi {
@GET("/user")
suspend fun getUser(@Path("id") id: String): User?
@GET("/posts")
suspend fun getPosts(@Query("userId") id: String): List<Post>
}
UserApiFake.kt
class UserApiFake : UserApi {
var users = (1..10).map {
User(id = it.toString(), username = "User$it")
}
var posts = (1..10).map{
Post(
id = it.toString(),
userId = it.toString(),
title = "Test title$it",
body = "Test body$it"
)
}
override suspend fun getUser(id: String): User? {
// Return the matching user Id
return users.find { it.id == id }
}
override suspend fun getPosts(id: String): List<Post> {
// GEt all the posts that belong to particular user
return posts.filter { it.id == id }
}
}
UserRepositoryImpl.kt
class UserRepositoryImpl(
private val api: UserApi
): UserRepository {
override suspend fun getProfile(userId: String): Result<Profile> {
return coroutineScope {
val userResult = async {
try {
Result.success(api.getUser(userId))
} catch(e: HttpException) {
Result.failure(e)
} catch(e: IOException) {
Result.failure(e)
}
}
val postsResult = async {
try {
Result.success(api.getPosts(userId))
} catch(e: HttpException) {
Result.failure(e)
} catch(e: IOException) {
Result.failure(e)
}
}
val fetchedUser = userResult.await().getOrNull()
if(fetchedUser != null) {
Result.success(
Profile(
user = fetchedUser,
posts = postsResult.await().getOrNull() ?: emptyList()
)
)
} else {
Result.failure(
userResult.await().exceptionOrNull() ?: Exception("Unknown error")
)
}
}
}
}
UserRepositoryImplTest.kt
class UserRepositoryImplTest {
private lateinit var repository : UserRepositoryImpl
private lateinit var api : UserApiFake
@BeforeEach
fun setUp() {
api = UserApiFake()
repository = UserRepositoryImpl(api = UserApiFake())
}
@Test
fun `Test getting profile`() = runBlocking {
val profileResult = repository.getProfile("1")
assertThat(profileResult.isSuccess).isTrue()
assertThat(profileResult.getOrThrow().user.id).isEqualTo("1")
val expectedPosts = api.posts.filter { it.userId == "1" }
val resultOfImpl = repository.getProfile("1")
assertThat(resultOfImpl.getOrThrow().user.id).isEqualTo(expectedPosts[0].userId)
}
}