This commit is contained in:
lunaticbum 2025-09-19 18:07:50 +09:00
parent 4b652c4df5
commit d6043543a1
2 changed files with 118 additions and 119 deletions

View File

@ -1,117 +1,117 @@
import com.google.gson.Gson //import com.google.gson.Gson
import okhttp3.* //import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType //import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody //import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody //import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File //import java.io.File
import java.io.IOException //import java.io.IOException
//
// Gson 파싱을 위한 데이터 클래스 //// Gson 파싱을 위한 데이터 클래스
data class LoginRequest(val userId: String, val userPw: String) //data class LoginRequest(val userId: String, val userPw: String)
data class LoginResponse(val token: String?) //data class LoginResponse(val token: String?)
//
/** ///**
* API 통합 테스트를 실행하는 메인 함수입니다. // * API 통합 테스트를 실행하는 메인 함수입니다.
* IDE에서 직접 실행() 있습니다. // * IDE에서 직접 실행(▶)할 수 있습니다.
*/ // */
fun main() { //fun main() {
val tester = ApiIntegrationTest() // val tester = ApiIntegrationTest()
tester.runBookmarkTest() // tester.runBookmarkTest()
} //}
//
class ApiIntegrationTest { //class ApiIntegrationTest {
//
private val client = OkHttpClient() // private val client = OkHttpClient()
private val gson = Gson() // private val gson = Gson()
private val jsonMediaType = "application/json; charset=utf-8".toMediaType() // private val jsonMediaType = "application/json; charset=utf-8".toMediaType()
//
// --- 테스트 환경 설정 --- // // --- 테스트 환경 설정 ---
private val baseUrl = "http://localhost:443" // private val baseUrl = "http://localhost:443"
private val testUserId = "lunaticbum" // private val testUserId = "lunaticbum"
private val testUserPw = "VioPup*383" // private val testUserPw = "VioPup*383"
private val imageToUpload = File("test_image.jpg") // 프로젝트 루트에 있는 이미지 파일 // private val imageToUpload = File("test_image.jpg") // 프로젝트 루트에 있는 이미지 파일
//
/** // /**
* 로그인 API를 호출하여 JWT 토큰을 반환합니다. // * 로그인 API를 호출하여 JWT 토큰을 반환합니다.
*/ // */
private fun loginAndGetToken(): String? { // private fun loginAndGetToken(): String? {
println("1. 로그인을 시도합니다...") // println("1. 로그인을 시도합니다...")
//
val loginRequest = LoginRequest(userId = testUserId, userPw = testUserPw) // val loginRequest = LoginRequest(userId = testUserId, userPw = testUserPw)
val requestBody = gson.toJson(loginRequest).toRequestBody(jsonMediaType) // val requestBody = gson.toJson(loginRequest).toRequestBody(jsonMediaType)
//
val request = Request.Builder() // val request = Request.Builder()
.url("$baseUrl/api/auth/login") // .url("$baseUrl/api/auth/login")
.post(requestBody) // .post(requestBody)
.build() // .build()
//
try { // try {
client.newCall(request).execute().use { response -> // client.newCall(request).execute().use { response ->
if (!response.isSuccessful) { // if (!response.isSuccessful) {
println("❌ 로그인 실패: ${response.code} - ${response.body?.string()}") // println("❌ 로그인 실패: ${response.code} - ${response.body?.string()}")
return null // return null
} // }
val responseBody = response.body?.string() // val responseBody = response.body?.string()
val loginResponse = gson.fromJson(responseBody, LoginResponse::class.java) // val loginResponse = gson.fromJson(responseBody, LoginResponse::class.java)
println("✅ 로그인 성공!") // println("✅ 로그인 성공!")
return loginResponse.token // return loginResponse.token
} // }
} catch (e: IOException) { // } catch (e: IOException) {
println("❌ 로그인 중 오류 발생: ${e.message}") // println("❌ 로그인 중 오류 발생: ${e.message}")
return null // return null
} // }
} // }
//
/** // /**
* 발급받은 토큰을 사용하여 북마크 저장 API를 호출합니다. // * 발급받은 토큰을 사용하여 북마크 저장 API를 호출합니다.
*/ // */
private fun saveBookmarkWithToken(token: String) { // private fun saveBookmarkWithToken(token: String) {
println("\n2. 발급받은 토큰으로 북마크 저장을 시도합니다... ${imageToUpload.absolutePath}") // println("\n2. 발급받은 토큰으로 북마크 저장을 시도합니다... ${imageToUpload.absolutePath}")
//
if (!imageToUpload.exists()) { // if (!imageToUpload.exists()) {
println("❌ 파일 없음: '${imageToUpload.path}' 경로에 테스트 이미지가 존재하지 않습니다.") // println("❌ 파일 없음: '${imageToUpload.path}' 경로에 테스트 이미지가 존재하지 않습니다.")
return // return
} // }
//
// Multipart 요청 본문 생성 // // Multipart 요청 본문 생성
val requestBody = MultipartBody.Builder() // val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM) // .setType(MultipartBody.FORM)
.addFormDataPart( // .addFormDataPart(
"bookmarkData", // "bookmarkData",
"""{"url":"https://m.cafe.daum.net/dotax/Elgq/4636033","userComment":"Kotlin 테스트 코멘트","visibility":"PUBLIC"}""" // """{"url":"https://m.cafe.daum.net/dotax/Elgq/4636033","userComment":"Kotlin 테스트 코멘트","visibility":"PUBLIC"}"""
) // )
.addFormDataPart( // .addFormDataPart(
"imageFile", // "imageFile",
imageToUpload.name, // imageToUpload.name,
imageToUpload.asRequestBody("image/jpeg".toMediaType()) // imageToUpload.asRequestBody("image/jpeg".toMediaType())
) // )
.build() // .build()
//
val request = Request.Builder() // val request = Request.Builder()
.url("$baseUrl/api/bookmarks/with-image") // .url("$baseUrl/api/bookmarks/with-image")
.header("Authorization", "Bearer $token") // 헤더에 JWT 토큰 추가 // .header("Authorization", "Bearer $token") // 헤더에 JWT 토큰 추가
.post(requestBody) // .post(requestBody)
.build() // .build()
//
try { // try {
client.newCall(request).execute().use { response -> // client.newCall(request).execute().use { response ->
println("✅ 북마크 저장 요청 완료! 응답 코드: ${response.code}") // println("✅ 북마크 저장 요청 완료! 응답 코드: ${response.code}")
println("응답 내용: ${response.body?.string()}") // println("응답 내용: ${response.body?.string()}")
} // }
} catch (e: IOException) { // } catch (e: IOException) {
println("❌ 북마크 저장 중 오류 발생: ${e.message}") // println("❌ 북마크 저장 중 오류 발생: ${e.message}")
} // }
} // }
//
/** // /**
* 전체 테스트 시나리오를 실행합니다. // * 전체 테스트 시나리오를 실행합니다.
*/ // */
fun runBookmarkTest() { // fun runBookmarkTest() {
val token = loginAndGetToken() // val token = loginAndGetToken()
if (token != null) { // if (token != null) {
saveBookmarkWithToken(token) // saveBookmarkWithToken(token)
} else { // } else {
println("\n테스트 중단: 로그인에 실패하여 북마크 저장을 진행할 수 없습니다.") // println("\n테스트 중단: 로그인에 실패하여 북마크 저장을 진행할 수 없습니다.")
} // }
} // }
} //}

View File

@ -1051,7 +1051,7 @@ class BookmarkApiController(
val visibility: String? val visibility: String?
) )
@PostMapping("api/with-image", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @PostMapping("/with-image", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
fun saveBookmarkWithImage( fun saveBookmarkWithImage(
@RequestPart("imageFile") imageFile: MultipartFile, @RequestPart("imageFile") imageFile: MultipartFile,
@RequestPart("bookmarkData") bookmarkDataJson: String, // 북마크 데이터는 JSON 문자열로 받음 @RequestPart("bookmarkData") bookmarkDataJson: String, // 북마크 데이터는 JSON 문자열로 받음
@ -1065,7 +1065,6 @@ class BookmarkApiController(
val uniqueFilename = "${UUID.randomUUID()}_${imageFile.originalFilename}" val uniqueFilename = "${UUID.randomUUID()}_${imageFile.originalFilename}"
val targetPath = Paths.get(uploadPath, uniqueFilename) val targetPath = Paths.get(uploadPath, uniqueFilename)
try { try {
// Files.createDirectories(targetPath.parent)
imageFile.transferTo(targetPath.toFile()) imageFile.transferTo(targetPath.toFile())
} catch (e: Exception) { } catch (e: Exception) {
return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()) return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build())