Skip to content

Commit

Permalink
[KAN-78] 음식점 조회 API에 MySQL 연결 - test code 세팅 및 기본 테스트코드
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkyoungdeok committed May 23, 2024
1 parent 9c9a5c3 commit 8327ffc
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 97 deletions.
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ dependencies {
testImplementation("org.testcontainers:junit-jupiter:1.17.1")
testImplementation("org.testcontainers:mysql:1.17.1")
testImplementation("org.testcontainers:elasticsearch:1.16.2")

// ES
testImplementation("org.springframework.boot:spring-boot-starter-data-elasticsearch")
}

allOpen {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class GetRestaurantService(
PageImpl(
restaurantProjections.content.map { it.toDto() },
pageable,
restaurantProjections.size.toLong()
restaurantProjections.content.size.toLong()
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ import io.kotest.extensions.spring.SpringTestLifecycleMode

class KotestProjectConfig : AbstractProjectConfig() {
override fun extensions() = listOf(SpringTestExtension(SpringTestLifecycleMode.Test))
}
}
26 changes: 26 additions & 0 deletions src/test/kotlin/com/restaurant/be/common/PageDeserializer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.restaurant.be.common

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.PageRequest

class PageDeserializer<T>(private val clazz: Class<T>) : JsonDeserializer<Page<T>>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Page<T> {
val mapper = (p.codec as ObjectMapper)
val node: JsonNode = mapper.readTree(p)
val content: List<T> = mapper.convertValue(
node.get("content"),
mapper.typeFactory.constructCollectionType(List::class.java, clazz)
)
val pageable = PageRequest.of(
node.get("pageable")?.get("pageNumber")?.asInt() ?: 0,
node.get("pageable")?.get("pageSize")?.asInt() ?: 0
)
return PageImpl(content, pageable, node.get("totalElements")?.asLong() ?: 0L)
}
}
66 changes: 4 additions & 62 deletions src/test/kotlin/com/restaurant/be/common/TestContainerConfig.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.restaurant.be.common

import com.github.dockerjava.api.model.PortBinding
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.MySQLContainer
import org.testcontainers.utility.DockerImageName
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL

object TestContainerConfig {

Expand Down Expand Up @@ -64,8 +64,6 @@ object TestContainerConfig {

// Initialize Elasticsearch
waitForElasticsearch()
createElasticsearchIndex()
insertSampleData()
}

private fun waitForElasticsearch() {
Expand All @@ -87,62 +85,6 @@ object TestContainerConfig {
}
}

private fun createElasticsearchIndex() {
val url =
URL("http://${elasticsearchContainer.host}:${elasticsearchContainer.getMappedPort(9200)}/restaurant")
val jsonPayload = """
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"id": {"type": "long"},
"name": {"type": "text"},
"original_category": {"type": "text"},
"address": {"type": "text"},
"naver_review_count": {"type": "long"},
"naver_rating_avg": {"type": "float"},
"review_count": {"type": "long"},
"rating_avg": {"type": "float"},
"like_count": {"type": "long"},
"number": {"type": "text"},
"image_url": {"type": "text"},
"category": {"type": "text"},
"discount_content": {"type": "text"},
"menus": {
"type": "nested",
"properties": {
"menu_name": {"type": "text"},
"price": {"type": "integer"},
"description": {"type": "text"},
"is_representative": {"type": "text"},
"image_url": {"type": "text"}
}
}
}
}
}
""".trimIndent()

val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "PUT"
connection.setRequestProperty("Content-Type", "application/json")
connection.doOutput = true
connection.outputStream.use { os ->
os.write(jsonPayload.toByteArray())
os.flush()
}

if (connection.responseCode != 200) {
println("Failed to create Elasticsearch index")
println(connection.errorStream.bufferedReader().readText())
} else {
println("Created Elasticsearch index")
}
}

private fun insertSampleData() {
val url =
URL("http://${elasticsearchContainer.host}:${elasticsearchContainer.getMappedPort(9200)}/restaurant/_doc/1")
Expand Down Expand Up @@ -184,4 +126,4 @@ object TestContainerConfig {
println("Data inserted into Elasticsearch")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.restaurant.be.common.util

import org.springframework.data.elasticsearch.annotations.Document
import org.springframework.data.elasticsearch.annotations.Field
import org.springframework.data.elasticsearch.annotations.FieldType
import javax.persistence.Id

@Document(indexName = "restaurant")
data class RestaurantDocument(
@Id
@Field(type = FieldType.Long, name = "id")
val id: Long,

@Field(type = FieldType.Text, name = "name")
val name: String,

@Field(type = FieldType.Text, name = "original_category")
val originalCategory: String,

@Field(type = FieldType.Text, name = "address")
val address: String,

@Field(type = FieldType.Long, name = "naver_review_count")
val naverReviewCount: Long,

@Field(type = FieldType.Float, name = "naver_rating_avg")
val naverRatingAvg: Float,

@Field(type = FieldType.Long, name = "review_count")
val reviewCount: Long,

@Field(type = FieldType.Float, name = "rating_avg")
val ratingAvg: Float,

@Field(type = FieldType.Long, name = "like_count")
val likeCount: Long,

@Field(type = FieldType.Text, name = "number")
val number: String,

@Field(type = FieldType.Text, name = "image_url")
val imageUrl: String,

@Field(type = FieldType.Text, name = "category")
val category: String,

@Field(type = FieldType.Text, name = "discount_content")
val discountContent: String,

@Field(type = FieldType.Nested, name = "menus")
val menus: List<MenuDocument>
)

data class MenuDocument(
@Field(type = FieldType.Text, name = "menu_name")
val menuName: String,

@Field(type = FieldType.Integer, name = "price")
val price: Int,

@Field(type = FieldType.Text, name = "description")
val description: String,

@Field(type = FieldType.Text, name = "is_representative")
val isRepresentative: String,

@Field(type = FieldType.Text, name = "image_url")
val imageUrl: String
)
71 changes: 71 additions & 0 deletions src/test/kotlin/com/restaurant/be/common/util/RestaurantUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.restaurant.be.common.util

import com.restaurant.be.restaurant.presentation.domain.entity.Menu
import com.restaurant.be.restaurant.presentation.domain.entity.Restaurant

object RestaurantUtil {

fun generateRestaurantDocument(
id: Long,
name: String = "default_name",
originalCategory: String = "default_category",
address: String = "default_address",
naverReviewCount: Long = 0,
naverRatingAvg: Float = 0.0f,
reviewCount: Long = 0,
ratingAvg: Float = 0.0f,
likeCount: Long = 0,
number: String = "default_number",
imageUrl: String = "default_image_url",
category: String = "default_category",
discountContent: String = "default_discount_content",
menus: List<MenuDocument> = emptyList()
): RestaurantDocument {
return RestaurantDocument(
id = id,
name = name,
originalCategory = originalCategory,
address = address,
naverReviewCount = naverReviewCount,
naverRatingAvg = naverRatingAvg,
reviewCount = reviewCount,
ratingAvg = ratingAvg,
likeCount = likeCount,
number = number,
imageUrl = imageUrl,
category = category,
discountContent = discountContent,
menus = menus
)
}

fun generateRestaurantEntity(
id: Long = 0,
name: String = "default_name",
originalCategories: String = "default_category",
reviewCount: Long = 0,
likeCount: Long = 0,
address: String = "default_address",
contactNumber: String = "default_number",
ratingAvg: Double = 0.0,
representativeImageUrl: String = "default_image_url",
viewCount: Long = 0,
discountContent: String? = null,
menus: MutableList<Menu> = mutableListOf()
): Restaurant {
return Restaurant(
id = id,
name = name,
originalCategories = originalCategories,
reviewCount = reviewCount,
likeCount = likeCount,
address = address,
contactNumber = contactNumber,
ratingAvg = ratingAvg,
representativeImageUrl = representativeImageUrl,
viewCount = viewCount,
discountContent = discountContent,
menus = menus
)
}
}
13 changes: 12 additions & 1 deletion src/test/kotlin/com/restaurant/be/common/util/UserUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ package com.restaurant.be.common.util

import com.restaurant.be.user.domain.entity.User
import com.restaurant.be.user.repository.UserRepository
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
import java.security.Principal

fun setUpUser(email: String, userRepository: UserRepository) {
val user = User(email = email, profileImageUrl = "")
userRepository.save(user)
}

SecurityContextHolder.getContext().authentication =
PreAuthenticatedAuthenticationToken(
Principal { email },
null,
listOf(SimpleGrantedAuthority("ROLE_USER"))
)
}
Loading

0 comments on commit 8327ffc

Please sign in to comment.