📌 Test Code
✔ TDD : 테스트가 주도하는 개발
✔ 단위 테스트 : 기능 단위의 테스트 코드를 작성하는 것
⚡ 단위 테스트
단위 테스트 장점
✔ 빠른 피드백 - 코드를 수정할 때마다 톰캣을 내렸다가 다시 실행하는 일을 반복하지 않아도 됨
✔ 자동 검증 - System.out.println()
을 통해 검증
✔ 개발자가 만든 기능 안전하게 보호 = 기존 기능이 잘 작동되는 것을 보장
테스트 코드 작성 프레임워크
- xUnit
- JUnit - Java
- DBUnit - DB
- CppUnit - C++
- NUnit - .net
- 우리 프로젝트에선 자바용인 JUnit5 사용
📌 Hello Controller 테스트 코드
✔ 일반적으로 패키지 명은 웹사이트 주소의 역순
Application.java
🔶 Application.java
: 프로젝트의 메인 클래스
package com.yerin.book.springbootwebservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootWebserviceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootWebserviceApplication.class, args);
}
}
✔ @SpringBootApplication
- 스프링 부트의 자동 설정
- 스프링 Bean 읽기와 생성을 모두 자동 설정
- 이 어노테이션이 붙은 곳부터 설정을 읽어감 -> 프로젝트의 최상단에 위치해야 함
✔ SpringApplication.run
- 내장 WAS 실행
- 항상 서버에 톰캣을 설치할 필요가 없게 되고, 스프링 부트로 만들어진 Jar 파일(실행 가능한 Java 패키징 파일)로 실행하면 됨
- 언제 어디서나 같은 환경에서 스프링 부트를 배포할 수 있음
HelloController.java
🔶 main/.../com.yerin.book.springbootwebservice/web/HomeController
package com.yerin.book.springbootwebservice.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
✔ @RestController
- 컨트롤러를 JSON 형식으로 반환하는 컨트롤러로 만들어줌
@ResponseBody
를 각 메소드마다 선언했던 것을 한번에 사용할 수 있게 됨
✔ @GetMapping
- HTTP Method인 Get의 요청을 받을 수 있는 API를 만들어줌
HelloControllerTest.java
📎 단축키 command + shift + T
-> Test 클래스 생성
🔶 src/test/.../web/HelloControllerTest
package com.yerin.book.springbootwebservice.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.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = HelloController.class)
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));
}
}
✔ @ExtendWith(SpringExtension.class)
- JUnit4에선
@RunWith(SpringRunner.class)
를 사용했지만 JUnit5에선 위에 어노테이션 사용 - 테스트를 진행할 때 JUnit에 내장된 실행자 외에 다른 실행자를 실행시킴
- 여기서는
SpringExtension.class
- 스프링 부트 테스트와 JUnit 사이에 연결자 역할
- 여기서는
✔ @WebMvcTest
- 여러 스프링 테스트 어노테이션 중, Web(Spring Mvc)에 집중할 수 있는 어노테이션
@Controller
,@ControllerAdvice
등을 사용 가능- 단,
@Service
,@Component
,@Repository
사용 불가능 - 여기서는 컨트롤러만 사용하기 때문에 선언
✔ @Autowired
- 스프링이 관리하는 빈 주입받음
✔ private MockMvc mvc
- 웹 API를 테스트할 때 사용
- 스프링 MVC 테스트의 시작점
- 이 클래스를 통해 HTTP GET, POST 등에 대한 API 테스트를 할 수 있음
✔ mvc.perform(get("/hello"))
MockMvc
를 통해/hello
주소로 HTTP GET 요청 보냄- 체이닝이 지원되어 아래와 같이 여러 검증 기능을 이어서 선언 가능
✔ .andExpect(status().isOk))
mvc.perform
의 결과를 검증- HTTP Header의 Status를 검증
- 우리가 흔히 알고있는 200, 404, 500 등의 상태를 검증
- 여기선 OK 즉, 200인지 아닌지 검증
✔ .andExpect(content().string(hello))
mvc.perform
의 결과를 검증- 응답 본문의 내용 검증
- Controller에서 "hello"를 리턴하기 때문에 이 값이 맞는지 검증
실행
SpringbootWebserviceApplication.java
실행
http://localhost:8081/hello 들어가보면 hello가 적혀있는 것을 확인할 수 있음
➡️ HelloController에서 반환한 문자열 (hello)
📌 Lombok
✔ Lombok : Getter, Setter, 기본 생성자, toString 등을 어노테이션으로 자동 생성해주는 라이브러리
✔ IntelliJ 2020.03 이후 버전에서는 기본 Plugin으로 Lombok이 설치되어 있음
- Plugins-Installed에서 확인
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
Gradle 5.x.x 이상
HelloController 코드 Lombok으로 전환
🔶 main/.../web/dto/HelloResponseDto
package com.yerin.book.springbootwebservice.web.dto;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
private final String name;
private final int amount;
}
✔ @Getter
- 선언된 모든 필드의 get 메소드를 생성해줌
✔ @RequiredArgsConstructor
- 선언된 모든 final 필드가 포함된 생성자를 생성해줌
- final이 없는 필드는 생성자에 포함하지 않음
HelloResponseDtoTest.java
📎 단축키 command + shift + T
-> Test 클래스 생성
🔶 src/test/.../web/dto/HelloResponseDtoTest.java
package com.yerin.book.springbootwebservice.web.dto;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;
class HelloResponseDtoTest {
@Test
public void 롬복_기능_테스트(){
//given
String name = "test";
int amount = 1000;
//when
HelloResponseDto dto = new HelloResponseDto(name, amount);
//then
assertThat(dto.getName()).isEqualTo(name);
assertThat(dto.getAmount()).isEqualTo(amount);
}
}
✔ assertThat
- assertj라는 테스트 검증 라이브러리의 검증 메소드
- 검증하고 싶은 대상을 메소드 인자로 받음
- 메소드 체이닝이 지원되어 isEqualTo와 같이 메소드를 이어서 사용 가능
✔ isEqualTo
- assertj의 동등 비교 메소드
- assertThat에 있는 값과 isEqualTo의 값을 비교해서 같을 때만 성공
-> JUnit의 기본 assertThat이 아닌 assertj
의 assertThat사용
HelloController.java 코드 추가
@RestController
public class HelloController {
...
@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name") String name, @RequestParam("amount")int amount){
return new HelloResponseDto(name, amount);
}
}
✔ @RequestParam
- 외부에서 API로 넘긴 파라미터를 가져오는 어노테이션
- 외부에서 name이란 이름으로 넘긴 파라미터를 메소드 파라미터 name에 저장
HelloControllerTest.java
package com.yerin.book.springbootwebservice.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.hamcrest.Matchers.is;
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 hello가_리턴된다() throws Exception{
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
@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 응답값을 필드별로 검증할 수 있는 메소드
- $를 기준으로 필드명 명시
- name과 amount 검증
스프링 부트와 AWS로 혼자 구현하는 웹 서비스_이동욱 지음 책을 읽고 정리하는 글입니다

PREV
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(1)
📌 1. 인텔리제이로 스프링 부트 시작하기 ⚡ 인텔리제이 소개 강력한 추천기능 훨씬 더 다양한 리팩토리과 디버깅 기능 이클립스의 깃(Git)에 비해 훨씬 높은 자유도 프로젝트 시작할 때 인덱싱
nyeroni.tistory.com
NEXT
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(3)
📌 JPA JPA : Java 표준 ORM (Object Relational Mapping) ⚡ 패러다임 불일치 문제 관계형 데이터베이스 : 어떻게 데이터를 저장할지에 초점이 맞춰진 기술 객체지향 프로그래밍 : 언어는 메시지를 기반으로
nyeroni.tistory.com
'프로젝트 > 스프링 부트와 AWS로 혼자 구현하는 웹 서비스' 카테고리의 다른 글
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(6) (0) | 2024.01.22 |
---|---|
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(5) (1) | 2024.01.22 |
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(4) (0) | 2024.01.22 |
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(3) (1) | 2024.01.22 |
스프링 부트와 AWS로 혼자 구현하는 웹 서비스(1) (1) | 2024.01.22 |