-
Notifications
You must be signed in to change notification settings - Fork 0
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
feature: 배너 이미지 조회 #18
The head ref may contain hidden characters: "16-feature-\uBC30\uB108-\uC774\uBBF8\uC9C0-\uC870\uD68C"
Changes from all commits
a4e94bb
d9997e4
78df0f3
e4116e0
417bf03
7c74c6b
0b66947
bec1f0b
28769f2
b938c23
3160c34
c3422fc
9db6793
18ffcc5
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 |
---|---|---|
|
@@ -2,8 +2,6 @@ name: CI With Pull Request | |
|
||
on: | ||
push: | ||
pull_request: | ||
types: [opened, reopened] | ||
|
||
jobs: | ||
build: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.petqua.application.banner | ||
|
||
import com.petqua.application.banner.dto.BannerResponse | ||
import com.petqua.domain.banner.BannerRepository | ||
import org.springframework.cache.annotation.Cacheable | ||
import org.springframework.stereotype.Service | ||
import org.springframework.transaction.annotation.Transactional | ||
|
||
@Transactional | ||
@Service | ||
class BannerService( | ||
private val bannerRepository: BannerRepository, | ||
) { | ||
|
||
@Cacheable("banners") | ||
Comment on lines
+14
to
+15
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. 캐시 좋네요! 이거 나중에 레디스로 이사하나요? 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. 나중에 cacheConfig에서 구현체만 수정하면 될 것 같군요! |
||
@Transactional(readOnly = true) | ||
fun readAll(): List<BannerResponse> { | ||
val banners = bannerRepository.findAll() | ||
return banners.map { BannerResponse.from(it) } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.petqua.application.banner.dto | ||
|
||
import com.petqua.domain.banner.Banner | ||
|
||
data class BannerResponse( | ||
val id: Long, | ||
val imageUrl: String, | ||
val linkUrl: String, | ||
) { | ||
companion object { | ||
fun from(banner: Banner): BannerResponse { | ||
return BannerResponse( | ||
id = banner.id, | ||
imageUrl = banner.imageUrl, | ||
linkUrl = banner.linkUrl, | ||
) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.petqua.common.cofig | ||
|
||
import org.springframework.cache.CacheManager | ||
import org.springframework.cache.annotation.EnableCaching | ||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
|
||
@EnableCaching | ||
@Configuration | ||
class CacheConfiguration { | ||
|
||
@Bean | ||
fun cacheManager(): CacheManager { | ||
val cacheManager = ConcurrentMapCacheManager() | ||
cacheManager.setCacheNames(listOf("banners")) | ||
return cacheManager | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.petqua.domain.banner | ||
|
||
import com.petqua.common.domain.BaseEntity | ||
import jakarta.persistence.Column | ||
import jakarta.persistence.Entity | ||
import jakarta.persistence.GeneratedValue | ||
import jakarta.persistence.GenerationType | ||
import jakarta.persistence.Id | ||
|
||
@Entity | ||
class Banner( | ||
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
val id: Long = 0L, | ||
|
||
@Column(nullable = false) | ||
val imageUrl: String, | ||
|
||
@Column(nullable = false) | ||
val linkUrl: String, | ||
) : BaseEntity() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.petqua.domain.banner | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository | ||
|
||
interface BannerRepository: JpaRepository<Banner, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.petqua.presentation.banner | ||
|
||
import com.petqua.application.banner.BannerService | ||
import com.petqua.application.banner.dto.BannerResponse | ||
import org.springframework.http.ResponseEntity | ||
import org.springframework.web.bind.annotation.GetMapping | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RequestMapping("/banners") | ||
@RestController | ||
class BannerController( | ||
private val bannerService: BannerService | ||
) { | ||
|
||
@GetMapping | ||
fun readAll(): ResponseEntity<List<BannerResponse>> { | ||
val response = bannerService.readAll() | ||
return ResponseEntity.ok(response) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.petqua.application.banner | ||
|
||
import com.petqua.domain.banner.Banner | ||
import com.petqua.domain.banner.BannerRepository | ||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.kotest.matchers.shouldBe | ||
import org.mockito.Mockito.atMost | ||
import org.mockito.Mockito.verify | ||
import org.springframework.boot.test.context.SpringBootTest | ||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE | ||
import org.springframework.boot.test.mock.mockito.SpyBean | ||
|
||
@SpringBootTest(webEnvironment = NONE) | ||
class BannerServiceTest( | ||
private var bannerService: BannerService, | ||
@SpyBean private var bannerRepository: BannerRepository, | ||
) : BehaviorSpec({ | ||
|
||
Given("Banner 조회 테스트") { | ||
bannerRepository.saveAll( | ||
listOf( | ||
Banner(imageUrl = "imageUrlA", linkUrl = "linkUrlA"), | ||
Banner(imageUrl = "imageUrlB", linkUrl = "linkUrlB"), | ||
Banner(imageUrl = "imageUrlC", linkUrl = "linkUrlC"), | ||
) | ||
) | ||
|
||
When("Banner를 전체 조회 하면") { | ||
val results = bannerService.readAll() | ||
|
||
Then("모든 Banner가 조회 된다") { | ||
results.size shouldBe 3 | ||
} | ||
} | ||
|
||
When("Banner가 캐싱 되어 있으면") { | ||
repeat(5) { bannerService.readAll() } | ||
|
||
Then("퀴리가 발생 하지 않는다") { | ||
verify(bannerRepository, atMost(1)).findAll() | ||
} | ||
} | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.petqua.presentation.banner | ||
|
||
import com.petqua.application.banner.dto.BannerResponse | ||
import com.petqua.domain.banner.Banner | ||
import com.petqua.domain.banner.BannerRepository | ||
import com.petqua.test.ApiTestConfig | ||
import io.restassured.module.kotlin.extensions.Extract | ||
import io.restassured.module.kotlin.extensions.Given | ||
import io.restassured.module.kotlin.extensions.Then | ||
import io.restassured.module.kotlin.extensions.When | ||
import org.assertj.core.api.SoftAssertions.assertSoftly | ||
import org.springframework.http.HttpStatus | ||
|
||
class BannerControllerTest( | ||
private val bannerRepository: BannerRepository | ||
) : ApiTestConfig() { | ||
init { | ||
Given("배너가 등록되어 있다.") { | ||
val banner = bannerRepository.saveAll( | ||
listOf( | ||
Banner(imageUrl = "imageUrlC", linkUrl = "linkUrlA"), | ||
Banner(imageUrl = "imageUrlB", linkUrl = "linkUrlB") | ||
) | ||
) | ||
|
||
When("배너 목록을 조회한다.") { | ||
val response = Given { | ||
log().all() | ||
} When { | ||
get("/banners") | ||
} Then { | ||
log().all() | ||
} Extract { | ||
response() | ||
} | ||
|
||
Then("배너 목록을 응답한다.") { | ||
val findBannerResponse = response.`as`(Array<BannerResponse>::class.java) | ||
|
||
assertSoftly { | ||
it.assertThat(response.statusCode).isEqualTo(HttpStatus.OK.value()) | ||
it.assertThat(findBannerResponse.size).isEqualTo(2) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.petqua.test | ||
|
||
import io.kotest.core.spec.style.BehaviorSpec | ||
import io.restassured.RestAssured | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.boot.test.context.SpringBootTest | ||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT | ||
import org.springframework.boot.test.web.server.LocalServerPort | ||
|
||
@SpringBootTest(webEnvironment = RANDOM_PORT) | ||
abstract class ApiTestConfig : BehaviorSpec() { | ||
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. 조아요~~ |
||
|
||
@LocalServerPort | ||
protected val port: Int = RestAssured.port | ||
|
||
@Autowired | ||
private lateinit var dataCleaner: DataCleaner | ||
|
||
init { | ||
afterContainer { | ||
dataCleaner.clean() | ||
} | ||
} | ||
} | ||
Comment on lines
+10
to
+24
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. 저는 너무 좋은데요! 한결 편해질 것 같아요!!! |
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.
도커 공부 해야하는데 언제하죠ㅋㅋㅋㅎ