-
Notifications
You must be signed in to change notification settings - Fork 57
Unit Tests improvements #137
base: main
Are you sure you want to change the base?
Changes from all commits
fde5b1e
f18d3f6
c60b401
0149805
9480825
74d9471
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,61 +15,47 @@ | |
*/ | ||
package com.android254.data.dao | ||
|
||
import android.content.Context | ||
import androidx.room.Room | ||
import androidx.test.core.app.ApplicationProvider | ||
import com.android254.data.db.Database | ||
import com.android254.data.db.model.Session | ||
import kotlinx.coroutines.flow.first | ||
import kotlinx.coroutines.runBlocking | ||
import com.google.common.truth.Truth | ||
import io.mockk.* | ||
import io.mockk.impl.annotations.MockK | ||
import kotlinx.coroutines.flow.* | ||
import kotlinx.coroutines.test.runTest | ||
import org.hamcrest.CoreMatchers.`is` | ||
import org.hamcrest.MatcherAssert.assertThat | ||
import org.junit.After | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.robolectric.RobolectricTestRunner | ||
import java.io.IOException | ||
|
||
@RunWith(RobolectricTestRunner::class) | ||
class SessionDaoTest { | ||
|
||
private lateinit var session: Session | ||
@MockK | ||
private lateinit var sessionDao: SessionDao | ||
private lateinit var db: Database | ||
Comment on lines
-35
to
-39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are using Robolectric because we want to test against a real db. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @michaelbukachi With robolectric: it slows down the tests a lot, but it's sometimes helpful if we really want to test the integration with the Android system There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest to use it only in a few places, not everywhere. Considering that tests performance are also very important and should be fast as possible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But it's okay if you guys think you want to stick with this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anselmoalexandre We are aware of its drawbacks. We used it to ensure all our queries were running as expected. |
||
|
||
@Before | ||
fun setup() { | ||
val context = ApplicationProvider.getApplicationContext<Context>() | ||
db = Room.inMemoryDatabaseBuilder( | ||
context, | ||
Database::class.java | ||
) | ||
.allowMainThreadQueries() // TODO Please delete me | ||
.build() | ||
sessionDao = db.sessionDao() | ||
} | ||
|
||
@After | ||
@Throws(IOException::class) | ||
fun tearDown() { | ||
db.close() | ||
} | ||
|
||
@Test | ||
fun `test sessionDao fetches all sessions`() = runTest { | ||
val session = Session( | ||
MockKAnnotations.init(this, relaxUnitFun = true) | ||
session = Session( | ||
id = 0, | ||
title = "Retrofiti: A Pragmatic Approach to using Retrofit in Android", | ||
description = "This session is codelab covering some of the best practices and recommended approaches to building an application using the retrofit library.", | ||
slug = "retrofiti-a-pragmatic-approach-to-using-retrofit-in-android-1583941090", | ||
session_format = "Codelab / Workshop", | ||
session_level = "Intermediate", | ||
) | ||
|
||
coJustRun { sessionDao.insert(session) } | ||
coEvery { sessionDao.fetchSessions() } returns flow { emit(listOf(session)) } | ||
} | ||
|
||
@Test | ||
fun `test sessionDao fetches all sessions`() = runTest { | ||
// Given | ||
sessionDao.insert(session) | ||
runBlocking { | ||
val result = sessionDao.fetchSessions().first().first() | ||
assertThat(session.title, `is`(result.title)) | ||
} | ||
|
||
// When | ||
val result = sessionDao.fetchSessions().first() | ||
|
||
// Then | ||
coVerify(atLeast = 1) { sessionDao.insert(session) } | ||
coVerify { sessionDao.insert(session) } | ||
Truth.assertThat(result.first().title).isEqualTo(session.title) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,12 +29,11 @@ import com.android254.data.network.models.responses.UserDetails | |
import com.android254.data.network.util.HttpClientFactory | ||
import com.android254.data.network.util.ServerError | ||
import com.android254.data.preferences.DefaultTokenProvider | ||
import com.google.common.truth.Truth | ||
import io.ktor.client.engine.mock.* | ||
import io.ktor.http.* | ||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.runBlocking | ||
import org.hamcrest.CoreMatchers.`is` | ||
import org.hamcrest.MatcherAssert.assertThat | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
@@ -55,19 +54,21 @@ class AuthApiTest { | |
|
||
@Test(expected = ServerError::class) | ||
fun `test ServerError is thrown when a server exception occurs`() { | ||
// Given | ||
val mockEngine = MockEngine { | ||
delay(500) | ||
respondError(HttpStatusCode.InternalServerError) | ||
} | ||
val httpClient = HttpClientFactory(DefaultTokenProvider(testDataStore)).create(mockEngine) | ||
val api = AuthApi(httpClient) | ||
runBlocking { | ||
api.logout() | ||
} | ||
|
||
// When | ||
runTest { api.logout() } | ||
} | ||
|
||
@Test | ||
fun `test successful logout`() { | ||
// Given | ||
val mockEngine = MockEngine { | ||
respond( | ||
content = """{"message": "Success"}""", | ||
|
@@ -77,14 +78,18 @@ class AuthApiTest { | |
} | ||
val httpClient = HttpClientFactory(DefaultTokenProvider(testDataStore)).create(mockEngine) | ||
val api = AuthApi(httpClient) | ||
runBlocking { | ||
val response = api.logout() | ||
assertThat(response, `is`(Status("Success"))) | ||
|
||
// Then | ||
runTest { | ||
api.logout().also { | ||
Truth.assertThat(it).isEqualTo(Status("Success")) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `test successful google login`() { | ||
// Given | ||
val content = """ | ||
{ | ||
"token": "test", | ||
|
@@ -106,18 +111,23 @@ class AuthApiTest { | |
} | ||
val httpClient = HttpClientFactory(DefaultTokenProvider(testDataStore)).create(mockEngine) | ||
val api = AuthApi(httpClient) | ||
runBlocking { | ||
val accessToken = AccessToken( | ||
token = "test", | ||
user = UserDetails( | ||
name = "Magak Emmanuel", | ||
email = "[email protected]", | ||
gender = null, | ||
avatar = "http://localhost:8000/upload/avatar/img-20181016-wa0026jpg.jpg" | ||
) | ||
|
||
val accessToken = AccessToken( | ||
token = "test", | ||
user = UserDetails( | ||
name = "Magak Emmanuel", | ||
email = "[email protected]", | ||
gender = null, | ||
avatar = "http://localhost:8000/upload/avatar/img-20181016-wa0026jpg.jpg" | ||
) | ||
val response = api.googleLogin(GoogleToken("some token")) | ||
assertThat(response, `is`(accessToken)) | ||
) | ||
|
||
// Then | ||
runTest { | ||
api.googleLogin(GoogleToken("some token")).also { | ||
Truth.assertThat(it).isEqualTo(accessToken) | ||
} | ||
} | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment. We can add it to the readme instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anselmoalexandre Good catch
Remove the suspend and return a flow 👯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @chepsi
This comment is just a heads up to @jumaallan so he can refactor this. @jumaallan please check this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anselmoalexandre saw it
I can raise a PR, but if you want, please feel free to refactor it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do the PR it's okay 👌🏿. Also, this was only heads up 😄