-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
๐ 2๋จ๊ณ - GitHub(HTTP) #105
Changes from all commits
be88d43
fc477b5
5c853e0
d41d689
882e300
f8ca1cc
0c87b22
3649fdc
6438cda
3b2fdcd
387b56b
75765ee
10bc813
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 |
---|---|---|
@@ -1,9 +1,9 @@ | ||
# TODO | ||
## Best Practice | ||
## Step1 | ||
## Step2 | ||
|
||
### ์ด๋ฒ ๋ฏธ์ TODO | ||
- ์์ ์ฝํ๋ฆฐ ๋ชจ๋์ธ domain ๋ชจ๋์ ๋ง๋ ๋ค. | ||
- ์์ ์ฝํ๋ฆฐ ๋ชจ๋์ธ data ๋ชจ๋์ ๋ง๋ ๋ค. | ||
- data ๋ชจ๋์ domain ๋ชจ๋์ ์์กดํด์ผ ํ๋ค. | ||
- app ๋ชจ๋์ domain ๋ชจ๋์ ์์กดํด์ผ ํ๋ค. | ||
- Repository ๋ชฉ๋ก์ ๊ฐ์ ธ์ค๋ ๊ธฐ๋ฅ์ data ๋ชจ๋์ ๊ตฌํ๋์ด์ผ ํ๋ค. | ||
- data ๋ชจ๋์ ๊ตฌํ์ฒด๋ ๋ชจ๋ internal class๋ก ์ ์ธํ๋ค. | ||
- HTTP ์์ฒญ์ ํตํด ๊ฐ์ ธ์ค๋ ๊ตฌํ์ฒด์ ๋ํ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ค. | ||
- OkHttp MockWebServer ์ด์ฉ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* @author Daewon on 01,September,2023 | ||
* | ||
*/ | ||
|
||
package camp.nextstep.edu.github.data | ||
|
||
import camp.nextstep.edu.github.data.response.GithubRepositoryResponse | ||
import camp.nextstep.edu.github.domain.model.GithubRepository | ||
|
||
internal fun List<GithubRepositoryResponse>.toDomainModels(): List<GithubRepository> { | ||
return this.map { it.toDomainModel() } | ||
} | ||
|
||
internal fun GithubRepositoryResponse.toDomainModel(): GithubRepository { | ||
return GithubRepository( | ||
fullName = fullName, | ||
description = description | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package camp.nextstep.edu.github.data.di | ||
|
||
import camp.nextstep.edu.github.data.retrofit.BASE_URL | ||
import camp.nextstep.edu.github.data.retrofit.GithubService | ||
import camp.nextstep.edu.github.data.retrofit.RetrofitNetwork | ||
|
||
internal object NetworkProvider { | ||
fun provideGithubService(baseUrl: String = BASE_URL): GithubService { | ||
return RetrofitNetwork | ||
.create(baseUrl) | ||
.create(GithubService::class.java) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* @author Daewon on 31,August,2023 | ||
* | ||
*/ | ||
|
||
package camp.nextstep.edu.github.data.network | ||
|
||
import camp.nextstep.edu.github.data.retrofit.GithubService | ||
import camp.nextstep.edu.github.data.retrofit.networkResult | ||
import camp.nextstep.edu.github.data.toDomainModels | ||
import camp.nextstep.edu.github.domain.Result | ||
import camp.nextstep.edu.github.domain.model.GithubRepository | ||
import camp.nextstep.edu.github.domain.repository.NetworkRepository | ||
|
||
|
||
internal class DefaultNetworkRepository( | ||
private val githubService: GithubService | ||
) : NetworkRepository { | ||
override suspend fun getRepositories(): Result<List<GithubRepository>> = | ||
networkResult { githubService.getRepositories().toDomainModels() } | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package camp.nextstep.edu.github.data.response | ||
|
||
import com.squareup.moshi.Json | ||
|
||
internal data class GithubRepositoryResponse( | ||
@Json(name = "full_name") | ||
val fullName: String, | ||
@Json(name = "description") | ||
val description: String? | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* @author Daewon on 31,August,2023 | ||
* | ||
*/ | ||
|
||
package camp.nextstep.edu.github.data.retrofit | ||
|
||
import camp.nextstep.edu.github.data.response.GithubRepositoryResponse | ||
import retrofit2.http.GET | ||
|
||
|
||
internal interface GithubService { | ||
@GET("repositories") | ||
suspend fun getRepositories(): List<GithubRepositoryResponse> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* @author Daewon on 22,April,2023 | ||
* | ||
*/ | ||
|
||
package camp.nextstep.edu.github.data.retrofit | ||
|
||
import camp.nextstep.edu.github.domain.Result | ||
|
||
internal inline fun <T> networkResult(transform: () -> T): Result<T> = try { | ||
Result.Success(transform.invoke()) | ||
} catch (e: Exception) { | ||
Result.Error(e) | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package camp.nextstep.edu.github.data.retrofit | ||
|
||
import com.squareup.moshi.Moshi | ||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory | ||
import okhttp3.OkHttpClient | ||
import okhttp3.logging.HttpLoggingInterceptor | ||
import retrofit2.Converter | ||
import retrofit2.Retrofit | ||
import retrofit2.converter.moshi.MoshiConverterFactory | ||
|
||
const val BASE_URL = "https://api.github.com/" | ||
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. ์ธ๋ถ์์ ๋ ธ์ถ๋๊ธฐ๋ณด๋ค ๋ด๋ถ์ ์ผ๋ก๋ง ํ์ฉ๋๋ ์ข์๊ฑฐ ๊ฐ์์! |
||
|
||
internal object RetrofitNetwork { | ||
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. Retrofit์ด ์๋ ๋ค๋ฅธ ๋คํธ์ํฌ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ๋ค์ด๋ฐ๋ ๋ณ๊ฒฝํด์ผํ ๊น์? |
||
|
||
private fun createOkhttpClient(): OkHttpClient { | ||
return OkHttpClient.Builder().apply { | ||
addInterceptor(HttpLoggingInterceptor()) | ||
}.build() | ||
} | ||
|
||
private fun createJsonAdapterFactory(): Converter.Factory = | ||
MoshiConverterFactory.create( | ||
Moshi.Builder() | ||
.add(KotlinJsonAdapterFactory()) | ||
.build() | ||
) | ||
|
||
fun create(baseUrl: String): Retrofit { | ||
return Retrofit.Builder() | ||
.client(createOkhttpClient()) | ||
.baseUrl(baseUrl) | ||
.addConverterFactory(createJsonAdapterFactory()) | ||
.build() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* @author Daewon on 01,September,2023 | ||
* | ||
*/ | ||
|
||
package camp.nextstep.edu.github.data | ||
|
||
import camp.nextstep.edu.github.data.di.NetworkProvider | ||
import camp.nextstep.edu.github.data.response.GithubRepositoryResponse | ||
import camp.nextstep.edu.github.data.retrofit.GithubService | ||
import com.google.common.truth.Truth.assertThat | ||
import kotlinx.coroutines.test.runTest | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import org.junit.Before | ||
import org.junit.Test | ||
import java.io.File | ||
|
||
|
||
class GithubServiceTest { | ||
|
||
private lateinit var server: MockWebServer | ||
private lateinit var githubService: GithubService | ||
|
||
@Before | ||
fun setUp() { | ||
server = MockWebServer() | ||
githubService = NetworkProvider.provideGithubService(server.url("").toString()) | ||
} | ||
|
||
@Test | ||
fun `test_json_์์ฒญ`() = runTest { | ||
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. ์๋ฏธ์๋ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์์ฑํด๋ ์ข์๊ฑฐ ๊ฐ์์! |
||
// given | ||
val response = MockResponse().setBody(File("src/test/resources/repositories.json").readText()) | ||
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.
๊ฐ์ด ํ ์คํธ๋ณ๋ก ์ฌ๋ฌ ์ผ์ด์ค์ jsonํ์ผ์ ํ์ฉํด๋ด๋ ์ข์์! |
||
server.enqueue(response) | ||
|
||
// when | ||
val actual = githubService.getRepositories() | ||
|
||
// then | ||
val expected = GithubRepositoryResponse( | ||
fullName = "mojombo/grit", | ||
description = "**Grit is no longer maintained. Check out libgit2/rugged.** Grit gives you object oriented read/write access to Git repositories via Ruby." | ||
) | ||
assertThat(actual).contains(expected) | ||
} | ||
|
||
@Test | ||
fun `test_json_์์ฒญ2`() = runTest { | ||
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. ์ค๋ณต๋์ ๋ถํ์ํ ํ
์คํธ ๊ฐ์์! |
||
// given | ||
val response = MockResponse().setBody(File("src/test/resources/repositories.json").readText()) | ||
server.enqueue(response) | ||
|
||
// when | ||
val actual = githubService.getRepositories() | ||
|
||
// then | ||
val expected = GithubRepositoryResponse( | ||
fullName = "jnicklas/uploadcolumn", | ||
description = "UploadColumn is no longer maintained, check out CarrierWave for an alternative" | ||
) | ||
assertThat(actual).contains(expected) | ||
} | ||
} |
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.
๊ธฐ์กด์ ์กด์ฌํ๋ runCatching ์ ๋์ผํ ๊ตฌ์กฐ๋ค์!
๊ตณ์ด ์๋ก ๋ง๋คํ์๋ ์์๊ฑฐ๊ฐ์์!