스프링 부트와 AWS로 혼자 구현하는 웹 서비스
: 인텔리제이, JPA, JUnit 테스트, 그레이들, 소셜 로그인, AWS 인프라로 무중단 배포까지
이동욱 저
2.3 롬복 소개 및 설치하기
Table of Content
자바 개발자들의 필수 라이브러리 롬복
롬복은 @Getter, @Setter, @NoArgsContructor 등 상당한 코드량을 줄일 수 있는 필수 라이브러리이다. build.gradle에 dependencies 부분에 lombok 라이브러리를 추가해야 한다. 하지만 교재에서의 의존성 추가 코드와 차이점이 있는데 Gradle 버전이 다르기 때문이다. 검색한 결과 위와 같이 Gradle 5.x미만, 5.x 이상은 위처럼 구분하여 롬복 의존성을 추가해주어야 한다.
현재 나의 Gradle 버전은 8.5 버전이 설치되어있으며 /root/gradle/wrapper/gradle-wrapper.properties 에서 그 버전을 확인 할 수 있다.
따라서 build.gradle 에 5.x 이상 버전에 알맞는 롬복 의존성을 추가해준다.
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.citefred'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
Java
복사
Hello Controller 코드를 롬복으로 전환하기
기존 코드를 롬복을 활용하여 변경하고자 한다. 하지만 기존 코드를 수정하는데 큰 프로젝트인 경우엔 쉽지 않다. 그 결과를 예측 할 수 없기 때문이다. 하지만 테스트 코드를 통해서 그 결과를 근접하게 예측, 검증 할 수 있다.
Dto 생성
HelloResponseDto.java를 통해 응답을 Dto로 반환하고자 한다.
package com.citefred.ldwspring.web.dto;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
private final String name;
private final int amount;
}
Java
복사
@Getter
•
선언된 모든 필드의 get 메소드를 생성해 줍니다.
•
ex) 아래와 같은 메소드로 총 6줄(필드가 많아지면 그 이상)의 코드를 @Getter 어노테이션 한 줄로 줄일 수 있다.
public String getName() {
return name;
}
public int getAmount() {
return amount;
}
Java
복사
@RequiredArgsConstructor
•
선언된 모든 final 필드가 포함된 생성자를 생성해 줍니다.
•
final이 없는 필드는 생성자에 포함되지 않습니다.
•
ex) 아래와 같은 생성자 코드를 자동으로 생성해준다.
public HelloResponseDto(String name, int amount) {
this.name = name;
this.amount = amount;
}
Java
복사
롬복 어노테이션들의 역할
위 어노테이션들은 코드를 단순하게 생략하는 역할을 하는 것이 아니라 컴파일러가 컴파일러가 이를 읽어서 소스 코드를 생성하거나 수정해주는 식이야. 그래서 컴파일된 .class 파일에는 이미 어노테이션에 의해 생성된 코드가 포함된 것을 확인 할 수 있다. 아래는 빌드를 통해 컴파일된 .class 파일에서 코드가 작성되있는 모습과 개발자가 작성한 코드는 생략된 모습을 비교한 모습이다.
테스트 코드를 통한 롬복 전환 테스트
Dto에 적용된 롬복의 기능이 잘 작동되는지 간단한 테스트를 추가해본다.
package com.citefred.ldwspring.web;
import com.citefred.ldwspring.web.dto.HelloResponseDto;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class HelloResponseDtoTest {
@Test
public void 롬복_기능_테스트() {
//given
String name = "test";
int amount = 1000;
//when
HelloResponseDto helloResponseDto = new HelloResponseDto(name, amount);
//then
assertThat(helloResponseDto.getName()).isEqualTo(name);
assertThat(helloResponseDto.getAmount()).isEqualTo(amount);
}
}
Java
복사
Dto에 전달한 name, amount와 현재 테스트 메소드에서 선언된 name, amount가 동일한지 검증하는 테스트로 정상적으로 작동하는 것을 확인 할 수 있다.
이는 롬복으로 getName(), getAmount()를 작성해준 @Getter 어노테이션, HelloResponseDto(name, amount)부분에서 생성자를 만들어주는 @RequiredArgsConstructor 어노테이션 또한 정상적으로 작동한다는 의미와도 같다.
given, when, then
•
현재 테스트 코드의 구조를 보면 given, when, then이라는 3단계 구조로 나누어져있다.
•
이 구조는 테스트의 명확성과 가독성을 높이기 위해 사용
1.
Given (주어진 상황): 테스트의 시작점이며, 테스트를 수행하기 위해 필요한 초기 상태를 설정하는 부분. 특정 조건이나 상황을 설정
2.
When (행동): 주어진 상황에서 어떤 특정한 동작이 발생하는 부분. 특정한 액션 또는 이벤트를 발생시켜 시스템이 어떻게 반응하는지를 확인하는 단계
3.
Then (결과): 특정 행동에 대한 결과를 기대하고, 그 결과를 확인하는 부분. 행동 이후에 기대되는 상태나 값이 맞게 나오는지 확인하는 단계로 테스트의 성공 또는 실패를 판단
assertThat()
•
assertj라는 테스트 검증 라이브러리의 검증 메소드
•
import static org.assertj.core.api.Assertions.assertThat;
•
검증하고 싶은 대상을 메소드 인자로 받음
•
메소드 체이닝이 지원되어 isEqualTo()와 같이 메소드를 이어서 사용 가능
isEqualTo()
•
assertj 에서 제공되는 값이 맞는지 확인하는 동등 비교 메소드
•
assertThat()의 값과 isEqualTo()의 값이 같을 때 테스트 성공
HelloController에 테스트된 Dto 사용
@RestController
public class HelloController {
...
@GetMapping("/hello/dto")
public HelloResponseDto helloResponseDto(@RequestParam("name") String name,
@RequestParam("amount") int amount) {
return new HelloResponseDto(name, amount);
}
}
Java
복사
@RequestParam
•
외부에서 API로 넘긴 파라미터를 가져오는 어노테이션
•
외부에서 name이란 변수명으로 넘긴 파라미터를 HelloResponseDto(name, amount)의 인자 중 하나인 name에 전달→ 이는 Dto클래스의 파라미터로 넘겨지게 됨
Dto를 반환하는 컨트롤러 테스트
package com.citefred.ldwspring.web;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
...
@Test
public void helloDto가_리턴() throws Exception{
String name = "hello";
int amount = 1000;
mvc.perform(get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value(name))
.andExpect(jsonPath("$.amount").value(amount));
}
}
Java
복사
param()
•
API 테스트 할 때 사용될 요청 파라미터 설정
•
값은 String만 허용됨, 따라서 int 정수인 amount는 String.valueOf(amount)로 형변환함
jsonPath()
•
JSON 응답값을 필드별로 검증 할 수 있는 메소드
•
$.를 기준으로 필드명을 명시
•
여기서는 name과 amount를 검증
Related Posts
Search