![[인프런 워밍업 클럽 3기] 백엔드 발자국 2주차](https://cdn.inflearn.com/public/files/blogs/a7976ad6-6765-474c-8fc3-d396c4594dca/워밍업클럽 3기.png)
[인프런 워밍업 클럽 3기] 백엔드 발자국 2주차
1개월 전
📒 2주차에 배운 내용
📌
Controller
,Service
,Repository
,DTO
개발과 테스팅, 그리고Tymeleaf fragments
에 대해 학습하는 시간이였다.
✏ 강의 중에 다뤘던 PresentationService
테스트
@DisplayName("활성화된 Introduction 만 조회하는데 성공한다. ")
@Test
fun testGetIntroductions() {/* given */
val introductions = mutableListOf<Introduction>()
(1..DATA_SIZE).forEach {
introductions.add(Introduction(content = "$it", isActive = it % 2 == 0))
}
val activeIntroductions = introductions.filter { it.isActive }
Mockito.`when`(presentationRepository.getActiveIntroductions()).thenReturn(activeIntroductions)
/* when */
val introductionDTOs = presentationService.getIntroductions()
/* then */
assertThat(introductionDTOs).hasSize(DATA_SIZE / 2)
introductionDTOs.forEach {
assertThat(it.content.toInt()).isEven()
}
}
@DisplayName("활성화된 Link 만 조회하는데 성공한다. ")
@Test
fun testGetLinks() {/* given */
val links = mutableListOf<Link>()
(1..DATA_SIZE).forEach {
links.add(Link(name = "$it", content = "$it", isActive = it % 2 != 0))
}
val activeLinks = links.filter { it.isActive }
Mockito.`when`(presentationRepository.getActiveLinks()).thenReturn(activeLinks)
/* when */
val linkDTOs = presentationService.getLinks()
/* then */
var expectedSize = DATA_SIZE / 2
if (DATA_SIZE % 2 != 0) expectedSize += 1
assertThat(linkDTOs).hasSize(expectedSize)
linkDTOs.forEach {
assertThat(it.content.toInt()).isOdd()
}
}
✏ Repository 성능 개선 -> N + 1
해결하기 (fetch join)
@Repository
interface ProjectRepository: JpaRepository<Project, Long> {
@Query("select distinct p from Project p left join fetch p.details where p.id = :id")
override fun findById(id: Long): Optional<Project>
}
📌
JPQL fetch Join
spring:
application:
name: kotlin-portfolio
jpa:
database: h2
open-in-view: false
show-sql: true
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
default_batch_fetch_size: 10 # batch size 조절
📌`application.yml` 에서 batch size 설정
✏ Mocking
을 활용한 Controller
테스트
val logger = KotlinLogging.logger {}
@AutoConfigureMockMvc
@SpringBootTest
@DisplayName("[API 컨트롤러 테스트]")
class PresentationApiControllerTest (
@Autowired private val mockMvc: MockMvc,
){
@DisplayName("Introductions 조회")
@Test
fun testGetIntroductions() {
/* given */
val uri = "/api/v1/introductions"
/* when */
val mvcResult = performGet(uri)
val contentAsString = mvcResult.response.contentAsString
val jsonArray = JSONArray(contentAsString)
/* then */
assertThat(jsonArray.length()).isPositive()
}
@DisplayName("Links 조회")
@Test
fun testGetLinks() {
/* given */
val uri = "/api/v1/links"
/* when */
val mvcResult = performGet(uri)
val contentAsString = mvcResult.response.contentAsString
val jsonArray = JSONArray(contentAsString)
/* then */
assertThat(jsonArray.length()).isPositive()
}
@DisplayName("Resume 조회")
@Test
fun testGetResume() {
/* given */
val uri = "/api/v1/resume"
/* when */
val mvcResult = performGet(uri)
val contentAsString = mvcResult.response.contentAsString
val jsonObject = JSONObject(contentAsString)
/* then */
logger.info{jsonObject.optJSONObject("experiences")}
assertThat(jsonObject.optJSONArray("experiences").length()).isPositive()
assertThat(jsonObject.optJSONArray("achievements").length()).isPositive()
assertThat(jsonObject.optJSONArray("skills").length()).isPositive()
}
private fun performGet(uri: String): MvcResult {
return mockMvc
.perform (MockMvcRequestBuilders.get(uri))
.andDo(MockMvcResultHandlers.print())
.andReturn()
}
}
📌 2주차 미션
1 대 다
관계를 갖는 테이블 설계하기 ✔Rest API
를 설계하기✔
댓글을 작성해보세요.