[Spring] 2장 스프링 부트에서 테스트 코드 작성
카테고리: springstudy
2장 - 스프링 부트에서 테스트코드를 작성하자
2.1 테스트 코드 소개
- TDD : 테스트 코드를 먼저 작성하는 것부터 시작, 즉 테스트가 주도하는 개발(실패하는 테스트 먼저 작성, 테스트가 통과하는 프로덕션 코드 작성, 통과하면 프로덕션 코드를 리팩토링)
- Unit Test : 기능 단위의 테스트 코드를 작성하는 것
2.2 Hello Controller 테스트 코드 작성하기
1
2
3
4
5
6
7
8
9
10
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Spring2Application {
public static void main(String[] args) {
SpringApplication.run(Spring2Application.class, args);
}
}
- @SpringBootApplication : 으로 인해 스프링 부트의 자동 설정, Bean 읽기와 생성을 모두 자동으로 설정
- SpringApplication.run() : 으로 인해 내장 Web Application Server를 실행
항상 서버에 톰캣을 설치할 필요 없고, 스프링 부트로 만들어진 Jar 파일(실행가능한 Java 패키징 파일)로 실행하면 됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// web/HelloController
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name") String name,
@RequestParam("amount") int amount) {
return new HelloResponseDto(name, amount);
}
}
- @RestController : 컨트롤러를 JSON 반환하는 컨트롤러로 만들어준다.
- 이전 인프런 강의 때 배웠던 것 잠깐!
- [Spring] Restful한 스프링 @ResponseBody vs @RestController
- @GetMapping : HTTP Method인 Get의 요청을 받을 수 있는 API
GET vs POST
-
GET
- 클라에서 서버로 어떤 리소스로부터 정보를 요청하기 위해 사용
- 데이터를 읽거나 검색할 때(조회)
- 요청을 전송할 때 URL 주소 끝에 파라미터로 포함되어 전송, 이 부분을 QueryString이라고 함
- 민감한 데이터를 다룰 때 GET 요청을 사용하면 안됨
-
POST
- 리소스를 생성/업데이트 하기 위해 서버에 데이터를 보내는 데 사용
- 전송해야될 데이터를 HTTP 메세지의 Body에 담아서 전송
- 길이의 제한 없이 데이터 전송 가능
- 데이터가 Body로 전송되고 내용도 눈에 안 보여서 GET보다 보안적으로 안전하다고 생각할 수 있지만 POST도 확인할 수 있기에 민감한 데이터의 경우 반드시 암호화 하기
-
✅ 테스트 - HelloControllerTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RunWith(SpringRunner.class)
@WebMvcTest
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void hello가_리턴된다() throws Exception {
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
2.3 롬복 소개 및 설치하기
롬복은 자바 개발 시 자주 사용하는 코드인 Getter, Setter, 기본 생성자, toString등을 어노테이션으로 자동 생성
1
2
3
dependencies {
implementation 'org.projectlombok:lombok'
}
Preferences > Build, Execution, Deployment > Compiler > Annotation Processors 에서
- Enable annotation processing 체크해주기
- build.gradle에 라이브러리 추가와 위의 체크는 프로젝트마다 진행해야 함.
2.4 Hello Controller 코드를 롬복으로 전환
1
2
3
4
5
6
7
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
private final String name;
private final int amount;
}
- @Getter : 선언된 모든 필드의 get메소드 생성
- @RequiredArgsConstructor : 선언된 모든 final 필드가 포함된 생성자를 생성
HelloController에도 새로 만든 ResponseDto를 사용하도록 코드를 추가해보자
1
2
3
4
5
6
@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name") String name,
@RequestParam("amount") int amount) {
return new HelloResponseDto(name, amount);
}
- @RequestParam : 외부에서 API로 넘긴 파라미터를 가져옴
- @RequestParam(“amount”) 외부에서 amount란 이름으로 넘긴 파라미터를 메소드 파라미터 amount (int amount)에 저장
✅ 테스트 - HelloControllerTest
1
2
3
4
5
6
7
8
9
10
11
12
13
@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", is(name)))
.andExpect(jsonPath("$.amount", is(amount)));
}
- .param : API 테스트할 때 사용될 요청 파라미터를 설정, String만 허용되기에 숫자/날짜 데이터 등록시 문자열로 변경하자
- jsonPath : JSON 응답값을 필드별로 검증할 수 있음, $을 기준으로 필드명 명시
JUnit4와 JUnit5의 혼용으로 인한 경고 해결
[JUnit] 경고: Runner org.junit.internal.runners.ErrorReportingRunner
- junit5에서는 @RunWith 어노테이션을 지원X → 대신 @ExtendWith 지원
- 따라서 org.junit.jupiter.api.Test 을 사용할 경우에는 @ExtendWith 사용
- junit4를 사용하려면 org.junit.jupiter.api.Test -> import org.junit.Test; 으로 변경!
DTO, DAO, VO란?
- DTO(Data Transfer Object)는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter, setter만 가진 클래스)
- DAO(Data Access Object)는 데이터베이스의 data에 접근하기 위한 객체로, 데이터베이스에 접근하기 위한 로직과 비즈니스 로직을 분리하기 위해 사용
- 보통 ibatis나 MyBatis 등에서 DAO라보 불리는 DB Layer 접근자임. JPA에선 Repository라고 부르며 인터페이스로 생성
- spring boot 에선 → ~Repository라고 인터페이스 생성 후 JpaRepository<Entity 클래스, PK 타입> 을 상속하면 기본 CRUD 메소드가 자동으로 생성
- VO(Value Object)는 값을 위해 쓰이며 사용하는 도중에 변경 불가능하고 오직 읽기만 가능한 read-Only 특징을 가진다. DTO와 유사하지만 DTO는 setter를 가지고 있어서 값 변경 가능
댓글남기기