JUnit 단위테스트
- JUnit5(Spring framework의 버전을 따름 - boot X)
- 사실상 Java의 표준 테스트 프레임워크
원활한 JUnit 호환을 위해 intelliJ 설정 변경 : Run testing using : IntelliJ IDEA
- Spring Boot Intializr를 이용해서 프로젝트를 생성하면 기본적으로 testImplementation >'org.springframework.boot:spring-boot-starter-test' 스타터가 포함되며, JUnit도 포함
- 데이터 전처리
- @BeforeEach : 테스트 케이스가 각각 실행될 때마다 테스트 케이스 실행 직전에 먼저 실행되어 초기화 작업진행
- @BeforeAll (static 메서드 앞): 테스트 케이스가 실행되기 전에 딱 한 번만 초기화
- @AfterEach, @AfterAll
- Assumption (가정) 특정환경에서만 테스트가 실행되도록 함
- assumeTrue(System.getProperty("os.name").startsWith("Windows"));
- 파라미터가 true면 아래 로직 실행
- 결과확인(assert)
- assertEquals(기대값, 실제값)
- assetNotNull(테스트 대상, 실패 시 출력문구)
- assertThrows(발생이 기대되는 예외클래스, 람다표현식 → 테스트대상 메서드) ex. assertThrows(NullPointerException.class, () -> getCryptoCurrency("XRP"));
- assertDoesNotThrow() : 예외가 발생되지 않기를 기대
슬라이스 테스트(계층별)
- 전체를 다 올리지 않고 목적에 맞는 에너테이션으로 테스트 진행
- @WebMVCTest @DataJpaTest
- 목업데이터 세팅을 하게 끔 가능하게 해준 툴 : 모키토
API 계층 테스트 : Controller @WebMvcTest
MockMvc는 Tomcat 같은 서버를 실행하지 않고 Spring 기반 애플리케이션의 Controller를 테스트할 수 있는 완벽한 환경을 지원해 주는 일종의 Spring MVC 테스트 프레임워크
Gson 의존성 추가 : 객체를 JSON 포맷으로 변환해주는 라이브러리
dependencies { ..
implementation 'com.google.code.gson:gson'}
- 컨트롤러 테스트 :
1) 테스트 클래스 구성
-
- @WebMvcTest : Controller에서 의존하는 컴포넌트들을 모두 일일이 설정
- @SpringBootTest, @AutoConfigureMockMvc : application context를 생성하고, Controller 테스트를 위한 애플리케이션의 자동 구성함
2) 테스트 메서드 작성
-
- Given : 테스트 요청 데이터
- Gson으로 json 형태로 변경
- When : 테스트 내용
- mockMvc.perform() : MockMvc로 테스트 대상 Controller의 핸들러 메서드에 요청을 전송 → ResultActions 타입의 객체 리턴
- Then : 전송한 데이터 검증 resultActions.andExpect()
- .andExpect(status().isCreated()) , .andExpect(*status*().isOk())
- header().string("Location", is(startsWith("/v11/members/")))
- Given : 테스트 요청 데이터
@SpringBootTest
@AutoConfigureMockMvc
public class MemberControllerTest {
@Autowired // 의존성 주입방법 중 하나
private MockMvc mockMvc;
@Autowired
private Gson gson;;
@DisplayName("CONTROLLER : Member post 테스트")
@Test
public void postMemberTest() throws Exception{
//1. given
MemberPostDto post = new MemberPostDto("jy@email.com","ㅂㅂㅂ","010-1234-5678");
String content = gson.toJson(post);
//2. when
ResultActions actions =
mockMvc.perform(
post("/rv1/members") //HTTP POST METHOD와 request URL을 설정
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content));
//3. then
actions
.andExpect(status().isCreated());
//.andExpect(header().string("Location", is(startsWith("/rv1/members/"))));
}
}
@SpringBootTest
@AutoConfigureMockMvc
public class MemberControllerTest {
@Autowired // 의존성 주입방법 중 하나
private MockMvc mockMvc;
@Autowired
private Gson gson;;
@DisplayName("CONTROLLER : member get 테스트")
@Test
void getMemberTest() throws Exception {
//1. given
MemberPostDto post = new MemberPostDto("jy@email.com","ㅂㅂㅂ","010-1234-5678");
String content = gson.toJson(post);
ResultActions actions =
mockMvc.perform(
post("/rv1/members") //HTTP POST METHOD와 request URL을 설정
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
String location = actions.andReturn().getResponse().getHeader("Location"); // "/v11/members/1"
//2-2. when-then
mockMvc.perform(
get(location)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.email").value(post.getEmail()))
.andExpect(jsonPath("$.data.name").value(post.getName()))
.andExpect(jsonPath("$.data.phone").value(post.getPhone()));
}
}
@WebMvcTest //컨트롤러 테스트
public class BookControllerTest {
@Autowired
private MockMvc mvc; //이건 모키토 프레임워크 아님
@MockBean //mokito annotation. import package 위치 확인
private BookService bookService;
//테스트 코드는 리턴타입 : void 메서드 내부에서 테스트 하고 종료
@DisplayName("CONTROLLER : BOOk LIST를 반환한다")
@Test //테스트 하는 영역이라고 명시
public void Book_MVC_Test() throws Exception{
//1. given : 테스트하기 위해서 필요한 데이터 등의 준비물들을 만들어 둔다
Book book = new Book("book", LocalDateTime.now());
//org 모키토 import
given(bookService.getBookList()).willReturn(Collections.singletonList(book)); //가정해서 갖고 있음.
//book 구현체가 없지만 시그니처를 만들어주어서 가정하고 테스트
//2. when : 테스트 해야 하는 내용
ResultActions resultActions = mvc.perform(get("/books"));
//결과를 반환받는 객체
//3. then : 검증(verify) 예상했던 결과의 참/거짓 여부를 판단하는 부분
resultActions
.andExpect(status().isOk())
.andExpect(view().name("book"))
.andExpect(model().attributeExists("bookList"))
.andExpect(model().attribute("bookList", contains(book)));
}
DataAccess 계층 테스트: Repository @DataJpaTest
테스트 시작 전 DB 상태를 깨끗하게 만든다.
@DataJpaTest : @Transactional 애너테이션을 포함. 하나의 테스트 케이스 실행이 종료되는 시점에 데이터베이스에 저장된 데이터는 rollback 처리
@DataJpaTest
public class MemberRepositoryTest {
@Autowired
private MemberRepository memberRepository; // DI
@Test
public void saveMemberTest() {
// given
Member member = new Member();
member.setEmail("hgd@gmail.com");
member.setName("홍길동");
member.setPhone("010-1111-2222");
// when
Member savedMember = memberRepository.save(member);
// then
assertNotNull(savedMember);
assertTrue(member.getEmail().equals(savedMember.getEmail()));
assertTrue(member.getName().equals(savedMember.getName()));
assertTrue(member.getPhone().equals(savedMember.getPhone()));
}
}
@DataJpaTest
public class MemberRepositoryTest {
@Test
public void findByEmailTest() {
// given
Member member = new Member();
member.setEmail("hgd@gmail.com");
member.setName("홍길동");
member.setPhone("010-1111-2222");
// when
memberRepository.save(member);
Optional<Member> findMember = memberRepository.findByEmail(member.getEmail());
// then
assertTrue(findMember.isPresent());
assertTrue(findMember.get().getEmail().equals(member.getEmail()));
}
}
'Coding > Back - Spring Framework' 카테고리의 다른 글
Spring View-Thymeleaf #Day16 (0) | 2023.09.11 |
---|---|
Spring Testing Mockito 3/3 (0) | 2023.09.11 |
[Error] JPA 테이블 생성 중 ORDER 테이블 : drop table if exists [*]order CASCADE 오류 (0) | 2023.09.04 |
Spring Testing 개념 1/3 #Day13 (0) | 2023.09.03 |
(review2) Spring 구성하기(Controller - Serivce - Repository) #Day12 (0) | 2023.09.01 |