https://github.com/Dev-Guccin
Guccin
https://github.com/Dev-Guccin
전체 방문자
오늘
어제
  • 분류 전체보기 (172)
    • 알고리즘 (140)
    • 삽질방지 (13)
    • SystemHacking (1)
    • 일상 (4)
    • 개발 (8)
    • 스프링 부트 REST API 개발일지 (5)
    • JPA (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 다이나믹프로그래밍
  • 최소힙
  • 유클리드호제법
  • heapq
  • 백트래킹
  • LIS
  • counter
  • 재귀
  • 유니온 파인드
  • 이분 탐색
  • 12015
  • 재귀함수
  • 다익스트라
  • Python
  • python3
  • 백준
  • BFS
  • MST
  • 최단경로
  • DFS
  • 그리디
  • 다이나믹 프로그래밍
  • 프로그래머스
  • 파이썬
  • 최대공약수
  • 스택
  • 큐
  • 이분탐색
  • DP
  • 그래프

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
https://github.com/Dev-Guccin

Guccin

개발

[JUnit5] JUnit5를 공부해보자(Spring Boot, REST API)

2022. 2. 24. 00:41

자바 개발자의 93%가 사용하는 단위 테스트 프레임워크. 스프링 부트 2.2버전 이상 부터는 기본적으로 제공됨.

 

JUnit5 모듈

Platform : 테스트를 실행해주는 런처 제공. TestEngine API 제공

Jupiter : JUnit5를 지원하는 TestEngine API구현체

Vintage : JUnit4와 3를 지원하는 TestEngine 구현체

(*작성한 버전에 따라 Jupiter를 사용하거나 Vintage를 사용한다.)

 

Annotation 사용법

@Test

테스트라는 것을 나타내는 어노테이션

// JUnit4
@Test(expected = Exception.class)
void create() throws Exception {}

// JUnit5
@Test
void create(){}

@BeforeAll

해당 클래스에 위치한 모든 테스트 메서드 실행전에 딱 한번 실행된다.

@AfterAll

해당 클래스에 위치한 모든 테스트 메서드 실행 후에 딱 한번 실행된다.


@BeforeEach

해당 클래스에 위치한 모든 테스트 메서드 실행 전에 실행되는 메서드

(*매 테스트 메서드마다 새로운 클래스를 생성하여 실행(비효율적))

@AfterEach

해당 클래스에 위치한 모든 테스트 메서드 실행 후에 실행되는 메서드

(*매 테스트 메서드마다 새로운 클래스를 생성하여 실행(비효율적))


@Disabled

테스트를 하고 싶지 않은 클래스나 메서드에 붙이는 어노테이션

@DisplayName

어떤 테스트인지 쉽게 표현할 수 있도록 해주는 어노테이션

공백, emoji, 특수문자 등을 모두 지원


@RepeatedTest

틀정 테스트를 반복 시키고 싶을 때 사용하는 어노테이션

반복 횟수와 반복 테스트 이름을 설정 가능

성능상의 이슈를 확인할때 사용한다.

@RepeatedTest(10)
@DisplayName("반복테스트")
void repeatedTest(){}

@RepeatedTest(value=10, name="{**displayName**}중 {**currentRepetition**} of {**totalRepetitions**})
@DisplayName("반복테스트")
void repeatedTest2(){}

@ParameterizedTest

테스트에 여러 다른 매개변수를 대입해가며 반복 실행할 때 사용하는 어노테이션

@ParameterizedTest
@CsvSource(value={"ACE,ACE:12", "ACE,ACE,ACE:13", "ACE,ACE,TEN:12"}, delimiter=':')
@DisplayName("에이스 카드가 여러 개일 때 합 구하기")
void calculatedCardSum(final String input, final int expected){
	final String[] inputs = input.split(",");
	
	for(final String number : inputs){
		final CardNumber cardNumber = Cardnumber.valueOf(number);
		dealer.receiveOneCard(new Card(cardNumber, CardType.CLOVER));
	}

	assertThat(dealer.calculateSource()).isEqualTo(expected); // 마지막에 CsvSource와 비교한다.
}

@Nested

테스트 클래스 안에서 내부 클래스를 정의해 테스트를 계층화 할 때 사용

내부클래스는 부모클래스의 멤버 필드에 접근가능

Before/After와 같은 테스트 생명주기에 관계된 메소드들도 계층에 맞춰 동작


Assertions

테스트 케이스의 수행 결과를 판별하는 메서드로 모든 Junit Jypiter Assertions는 static메서드다.

(*static이란 공유개념과 같아서 여러 객체가 하나의 메모리를 참조하여 값을 공유한다. → 효율적인 메모리 사용가능. 즉, static으로 메소드를 선언했을때 인스턴스없이 해당 메모리로 접근하여 호출이 가능해진다.)

assertAll

@Test
public void create_study(){
	Study study = new Study();
	assertNotNull(study);
	assertEquals(Status.STARTED, study.getStatus(), "처음 상태값이 DRAFT");
	// 만약 여기서 실패한다면 원래는 아래의 assertTrue가 실행되지 않는다.
	assertTrue(study.getLimit() > 0, () -> "최대 인원은 0보타 커야한다.")
}
@Test
public void create_study(){
	Study study = new Study();
	assertAll( // 중간에 실패한 assertion이 있어도 전부 실행한다.
		()->assertNotNull(study),
		()->assertEquals(Status.STARTED, study.getStatus(), "처음 상태값이 DRAFT"),
		()->assertTrue(study.getLimit() > 0, () -> "최대 인원은 0보타 커야한다.")
	);
}

assertThrows

@Test(expected = Exception.class)
void create() throws Exception{}

@Test
void excptionTrow(){
	Exception e = **assertThrows**(Exception.class, ()-> new Test(-10));
	assertDoesNotThrow(()->System.out.println("Do Something"));
}

assertTimeout

특정시간 안에 실행이 완료되는지 확인가능하다.


Assumption

전제문이 true라면 실행, false라면 종료한다.

assumeTrue : false일 때 이후 테스트 전체가 실행되지 않는다.

assumingThat : 파라미터로 전달된 코드블럭만 실행되지 않는다.

void dev_env_only(){
	assumeTrue("DEV".equals(System.getenv("ENV")), ()->"개발환경이 아닙니다.");
	//위의 가정이 false라면 이후 코드가 실행되지 않는다.
	assertEquals("A","A"); 
}
void some_test(){
	assumingThat("DEV".equals(System.getenv("ENV")),
		()->{
				assertEquals("A","A"); //해당 단정문만 실행되지 않는다.
		});
	assertEquals("A","A"); // 위의 가정과 상관없이 무조건 실행된다.
}

 

실제 코드를 적용해보자

간단하게 파라미터로 해당 값을 더해주고 리턴하는 REST API가 존재한다. 이때 Test코드를 짜보자.

@RestController
public class TestController {

    @GetMapping("/add")
    public int add(@RequestParam int A, @RequestParam int B){
        return A+B;
    }
}
@AutoConfigureMockMvc // MockMvc에 필요한 주입을 한다.
@SpringBootTest // 테스트에 필요한 거의 모든 의존성을 제공한다.
public class TestControllerTest {

		// MockMvc는 웹 어플리케이션을 애플리케이션 서버에 배포하지 않고 
		// 테스트용 MVC환경을 만들어 요청 및 전송, 응답기능을 제공해주는 유틸리티 클래스다
    @Autowired
    private MockMvc mockMvc; 

    @Test
    public void addTest() throws Exception {
        // 준비
        String url = "/add?A=1&B=2";
        // 실행
        final ResultActions actions = mockMvc.perform(MockMvcRequestBuilders.get(url)
                .contentType(MediaType.APPLICATION_JSON));
        // 단언
        actions.andExpect(result->{
                    MockHttpServletResponse response = result.getResponse();
                    System.out.println(response.getContentAsString());
                    assertEquals("3",response.getContentAsString());
                });
    }
}

 

 

래퍼런스

https://www.youtube.com/watch?v=EwI3E9Natcw&t=191s

https://wikidocs.net/228#static_1

https://velog.io/@jkijki12/Spring-MockMvc

 

저작자표시

'개발' 카테고리의 다른 글

JAVA의 스레드를 공부하자  (0) 2022.02.26
[TDD] 자바와 JUnit을 활용한 실용주의 단위 테스트 (작성중)  (0) 2022.02.24
JAVA의 Servlet이 뭐지?  (0) 2022.02.19
JAVA 인터페이스는 왜 쓰는 걸까?  (0) 2022.02.18
OOP(Object-Oriented Programming, 객체 지향 프로그래밍)이 머냐?  (0) 2022.02.16
    '개발' 카테고리의 다른 글
    • JAVA의 스레드를 공부하자
    • [TDD] 자바와 JUnit을 활용한 실용주의 단위 테스트 (작성중)
    • JAVA의 Servlet이 뭐지?
    • JAVA 인터페이스는 왜 쓰는 걸까?
    https://github.com/Dev-Guccin
    https://github.com/Dev-Guccin
    https://github.com/Dev-Guccin

    티스토리툴바