Java 기반의 Java를 위한 단위 테스트를 위한 프레임워크
이다.
Annotation 기반으로 테스트를 지원하며, Assert를 통해서 (예상, 실제 )를 통해 검증한다.
참고로, Spring Boot는 버전 2.2
부터 JUnit5
를 기본적으로 사용할 수 있도록 설정되었다.
Junit을 알아보기 전에 먼저 개념을 정리해봅시다.
TDD(Test-driven Development)
테스트 주도 개발에서 사용하지만, 코드의 유지보수 및 운영환경에서의 에러를 미리 방지하기 위해서 단위 별로 검증 하는 테스트 프레임워크
https://velog.io/@mooh2jj/TDD란
단위테스트
작성한 코드가 기대하는 대로 동작을 하는지 가장 작은 소프트웨어를 실행하여 검증하는 테스트.
통합테스트
단위 테스트보다 더 큰 동작을 달성하기 위해 여러 모듈들을 모아 이들이 의도대로 협력하는지 확인하는 테스트.
기능테스트(E2E 테스트)
사용자 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인하는 테스트, 즉, 사용자가 직접 사용하는 웹 브라우저나 모바일 앱부터 시작해서 DB, 외부 서비스에 이르기까지 모든 구성 요소를 하나로 엮어서 진행한다. QA팀이 하는 테스트가 보통 기능테스트이다.
통합 테스트
는 단위 테스트와 달리 개발자가 변경할 수 없는 부분(ex. 외부 라이브러리)까지 묶어 검증할 때 사용한다. 이는 DB에 접근
하거나 전체 코드와 다양한 환경이 제대로 작동하는지 확인
하는데 필요한 모든 작업을 수행할 수 있다. 그러나, 통합 테스트가 응용 프로그램이 완전하게 작동하는 걸 무조건 증명하지는 않는다.
통합 테스트의 장점은 단위 테스트에서 발견하기 어려운 버그를 찾을 수 있다는 점이다. 예를 들어, 통합 테스트에서는 환경 버그(ex. 싱글 코어 CPU에서는 잘 실행되나 쿼드 코어 CPU에서는 잘 실행되지 않음)이 발생할 수 있다.
한편, 통합 테스트의 단점은 단위 테스트보다 더 많은 코드를 테스트하기 때문에 신뢰성이 떨어질 수 있다는 점
이다. 또, 어디서 에러가 발생했는지 확인하기 쉽지 않아 유지보수하기 힘들다는 점도 있다.
통합 테스트에서는 클래스 상단에 @SpringBootTest
어노테이션을 붙여 를 수행할 수 있다.
H2 메모리
실제 사용 DB
✅참고: 스프링 부트에 아무런 설정도 하지 않으면 h2 DB(embeded DB)를 메모리 모드로 JVM안에서 실행한다.
Mock
: 유닛 테스트 등을 작성할 때 해당 코드가 의존성을 가지고 있다면 그 의존하는 부분을 가짜로 대체한 객체 @Mock
private StudyGroupRepository studyGroupRepository;
@InjectMocks
private StudyGroupService studyGroupService;
stub
: 아직 준비되지 못한 코드를 미리 기대한 답변
으로 반환할 수 있도록 하는 메커니즘. // stubbing , Mocikto.when()
when(mockedList.get(0)).thenReturn("ok");
when(mockedList.get(1)).thenThrow(new RuntimeException());
// stubbing, BDDMockito.given() => 주로 애를 많이 사용함.
given(mockedList.get(0)).willReturn("ok");
둘 모두의 목적은
가짜 객체가 실제로 동작하는 것처럼 보이게 만들어놓은 객체를 활용하여, 호출자를 실제 구현물로부터 격리
시켜 독립적인 테스트를 진행할 수 있도록 하는 것이다.
출처: https://hyeonyeee.tistory.com/98 [hyeoneee's blog]
먼저 라이브러리를 추가해야 합니다.
Junit4
// gradle
testImplementation 'junit:junit:4.12'
Junit5
자바 8이상부터 사용가능, JUnit Platform과 Junit jupiter, Junit Vintage 결합한 형태.
Spring Boot는 버전 2.2
부터 JUnit5
를 기본적으로 사용할 수 있도록 설정되었다.
기본적으로 이 디팬더시로 JUnit5 의존성 라이브러리들이 전부 가져다 준다.
// gradle
testImplementation 'org.springframework.boot:spring-boot-starter-test'
https://steady-coding.tistory.com/349
그리고 Test용 클래스를 만들어줍니다.
이 클래스는 인텔리제이라면
ctrl + shift + T
를 눌러주면 자동 생성됩니다.
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// test에서 lombok 사용 -> @Sl4j 사용가능
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
// test sql 확인용
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0'
import org.junit.jupiter.api.Test; // 꼭 @Test는 jupiter.api.Test로 받아야!
@Slf4j
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // 이걸 같이 붙여줘야 @Order 적용이 됨!
@SpringBootTest // 통합테스트
@Transactional // rollback
@ActiveProfiles("test") // application-test.yml 설정을 받음
class MemoTest {
@Autowired
private MemoRepository memoRepository;
@Order(1)
@Test
@DisplayName("saveTest")
public void save() {
LongStream.rangeClosed(1,30).forEach( i -> {
Memo memo = Memo.builder()
.title("title_"+i)
.content("content_"+i)
.build();
memoRepository.save(memo);
});
}
@Order(2)
@Test
@DisplayName("getAll 테스트")
public void getAll() {
List<Memo> all = memoRepository.findAll();
log.info("all : {}", all);
System.out.println("all = " + all);
assertThat(all.size()).isGreaterThan(30); // Assertions -> assertj.core 패키지 import
}
}
클래스 Calculator, 그리고 그 안에 메서드 sum()를 만들어줍시다.
package com.example.mocktest.model;
public class Calculator {
public int sum(int num1, int num2) {
return num1 + num2;
}
}
package com.example.mocktest.model;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void sum() {
Calculator calculator = new Calculator();
int result = calculator.sum(10, 20);
assertEquals(30, result);
}
}
여기서 assertEquals(expected, actual)
는 두 값이 같은지 여부를 판단하는 Junit jupiter 단언(assert) 메서드
이다.
x=y가 맞다면 결과는 이렇게 나온다.
Assertions 라이브러리로 두 가지를 들 수 있다.
1) Jupiter
2) Assertj
가독성이 좋고 쉽게 사용하기에는 여러 개발자분들은(대표적 백기선, 김영한 등) AssertJ
를 많이 추천해준다.
assertThat(dto.getName()).isEqualTo(name);
https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/