자바 프로그래밍용 단위 테스트 프레임워크.
테스트 작성자를 위한 API 모듈과 실행을 위한 API가 분리되어있음
java 8 이상 버전, jdk8 버전 이상에서만 사용 가능
Spring Boot 2.2.x 이후 버전부터는 JUnit5를 기본적으로 제공
JUnit5는 크게 JUnit Platform, JUnit Jupiter, JUnit Vintage 모듈로 구성되어 있다
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform : JVM 기반 테스팅 프레임워크 실행을 위한 기반 모듈, Test를 실행하기 위한 전반적인 사항들을 제공하는 역할
JUnit Jupiter : TestEngine을 구현한 엔진
JUnit Vintage : JUnit3, 4 버전으로 작성된 테스트 코드 실행 시 사용되는 모듈
assertEquals([message], expected, actual)
: 두 값이 같은 지 비교
assertSame([message], expceted, actual), assertNotSame([message], expceted, actual)
: 두 객체가 동일한 객체인지 비교
assertTrue([message], expceted), assertFalse([message], expceted)
: 참/거짓 판별
assertNull([message], expceted), assertNotNull([message], expceted)
: null여부 판단 fail([message]) 테스트 실패로 판단
@RunWith : JUnit에서 기본으로 제공하는 러너가 아닌 스프링 러너를 사용하기위한 어노테이션
@SpringBootTest : 테스트에 필요한 모든 설정과 빈들을 자동으로 초기화 하는 역할을 수행
@TEST : 해당 메서드가 테스트 메서드임을 명시
@ParameterizedTest : 매개변수가 있는 테스트 메서드임을 명시
@RepeatedTest : 반복되는 테스트임을 명시
@TestFactory : 동적 테스트임을 명시. 런타임에 생성되는 동적 테스트. 테스트 케이스를 위한 팩토리
@TestTemplate : 여러번 호출 가능한 테스트 템플릿
@TestMethodOrder : 테스트용 메서드 실행 순서 명시
@BeforeEach : 현재 클래스에서 각각의 @Test, @RepeatedTest, @ParameterizedTest, @TestFactory가 있는 메서드들 보다 먼저 실행
@BeforeAll : 모든 테스트 메서드보다 먼저 실행
@AfterAll : 모든 테스트 메서드보다 이후에 실행
@AfterEach : 각각의 테스트 메서드보다 이후에 실행
@DisplayName : 테스트 클래스 or 메서드의 사용자 정의 이름 표시
* 어노테이션 사용, JUnit 테스트 예시
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
class MyClassTest {
@Test
void create() {
MyClass myclass = new MyClass();
assertNotNull(myclass);
System.out.println("create");
}
@Test
@Disabled
void create1() {
System.out.println("create1");
}
@BeforeAll
static void beforeAll() {
System.out.println("before all");
}
@AfterAll
static void afterAll() {
System.out.println("after all");
}
@BeforeEach
void beforeEach() {
System.out.println("before each");
}
@AfterEach
void afterEach() {
System.out.println("after each");
}
}
프로젝트 의존성에 테스트 스타터가 등록되어 있기 때문에 테스트에 필요한 여러 라이브러리들도 자동으로 추가.
1. pom.xml JUnit설정
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
2. 테스트를 적용 시킬 클래스 생성
package kr.co.zikapi.sample.JUnitTest;
public class JUnitSample {
public int add(int a, int b) {
return a + b;
}
public String hello() {
return "Hello";
}
}
3. 테스트케이스 생성
만들었던 클래스를 마우스로 우클릭하고 New의 JUnit Test Case 클릭.
관련 설정과 테스트 원하는 메서드를 선택 할 수 있다.
설정 완료하면 해당 샘플 클래스의 테스트 파일이 생성 된다.
값에 fail("Not yet implemented") 는 생성 시 자동으로 입력되는 값이므로 지우고 테스트 코드를 작성하면 된다.
1. 테스트 코드 작성 전
package kr.co.zikapi.sample.JUnitTest;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class JUnitSampleTest {
@Test
void testAdd() {
fail("Not yet implemented");
}
@Test
void testHello() {
fail("Not yet implemented");
}
}
2. 테스트 코드 작성 후
package kr.co.zikapi.sample.JUnitTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
class JUnitSampleTest {
@Test
@DisplayName("1 + 1 = 2")
void testAdd() {
JUnitSample jUnitSample = new JUnitSample();
assertEquals(2, jUnitSample.add(1, 1), "1 + 1 should equal 2");
}
@Test
@DisplayName("헬로우 출력 테스트")
void testHello() {
JUnitSample jUnitSample = new JUnitSample();
assertEquals("Hello", jUnitSample.hello(), "Hello가 출력 되어야함");
}
}
4. 테스트 실행
테스트 코드가 작성 된 파일을 JUnit 테스트로 실행
성공 시 초록색 :
실패 시 빨강색 :
테스트 하려는 객체와 비슷한 가짜 객체를 만들어서 테스트에 필요한 기능만 가지도록 모킹을 하면 테스트가 쉬워진다. (Mock 이란 테스트를 위해 만든 모형을 의미)
MockMvc :
요청과 응답을 의미하는 객체, 컨트롤러 테스트를 할 수 있게 해주는 라이브러리.
서버에 배포하지 않고도 스프링 MVC의 동작을 재현할 수 있는 클래스
perform() :
MockMvcRequestBuilders를 사용해 설정한 요청 데이터를 perform()의 인수로 전달, get() / post() / put() / delete() 와 같은 메서드 제공
perform()에서 반환된 ResultActions() 호출
andExpect() :
서버의 응답 결과 검증
status() :
StatusResultMatchers 객체를 리턴. 응답 상태 코드 검증 가능
isOk() :
응답 상태 코드가 200인지 확인
isNotFound() :
응답 상태 코드가 404 NotFound인지 확인
view() :
컨트롤러가 리턴하는 뷰를 검증.
andExpect(view().name("hello")) 는 리턴한 뷰 이름이 "hello"인지 검증
redirectedUrl() :
리턴하는 결과가 리다이렉트 응답일 경우.
andExpect(redirectedUrl("/index")) 는 "/index" 화면으로 리다이렉트 했는지 검증
model() :
컨트롤러에 저장한 모델의 정보들을 검증.
attributeExists(String name)는 name에 해당하는 데이터가 model에 포함되어 있는지 검증.
attribute(String name, Object value)는 name에 해당하는 데이터가 value 객체인지 검증.
andDo() :
생성된 요청과 응답 메시지를 모두 확인해 보고 싶을때 사용.
# 예시
@Test
public void testHome() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("/WEB-INF/index.jsp"));
}
: 서블릿 컨테이너를 모킹(테스트용 모형 컨테이너를 사용하기 때문에 간단하게 컨트롤러 테스트 가능)
@Controller, @RestController가 설정된 클래스들을 찾아 메모리에 생성.
@Service나 @Repository가 붙은 객체들은 생성하지 않는다.
: @SpringBootTest(webEnvironment=WebEnvironment.MOCK) 설정으로 모킹. 컨트롤러 뿐만 아니라 @Service나 @Repoisotry가 붙은 객체들도 모두 테스트.
@WebMvcTest와 @SpringBootTest는 각자 서로의 MockMvc를 모킹하기 때문에 충돌이 발생할 수 있어 같이 사용 불가하다.
컨트롤러에서 단순히 서비스가 제공하는 메소드를 호출하여 사용하는 경우.
@MockBean을 사용하여 특정 타입의 객체를 모킹 해 비즈니스 객체(ServiceImpl)를 생성하지 않고도 테스트 케이스 생성 가능하다.
@Runwith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.Mock)
@AutoConfigureMockMvc
public class ControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private Service service;
@Test
public void test() throws Exception {
when(service.hello("둘리")).thenReturn("Hello: 둘리");
mockMvc.perform(get("/hello").param("name", "둘리"))
.andExpect(status().isOk())
.andExpect(content().string("Hello : 둘리"))
.andDo(print());
}
}