테스트 코드

Sirius·2024년 7월 10일
  • 테스트 코드: 작성한 코드가 의도대로 잘 동작하고 예상치 못한 문제가 없는지 확인할 목적으로 작성하는 코드

테스트코드 패턴

  • given: 테스트 실행을 준비하는 단계
  • when: 테스트를 진행하는 단계
  • then: 테스트 결과를 검증하는 단계

스프링 부트 3와 테스트

spring-boot-starter-test의 도구

1) JUnit: 자바 프로그래밍 언어용 단위 테스트 프레임워크
2) Spring Test & Sprint Boot Test: 스프링 부트 애플리케이션을 위한 통합 테스트 지원
3) AssertJ: 검증문인 어설션을 작성하는 데 사용되는 라이브러리
4) Hamcrest: 표현식을 이해하기 쉽게 만드는 데 사용되는 Matcher 라이브러리
5) Mockito: 테스트에 사용할 가짜 객체인 목 객체를 쉽게 만들고, 관리하고, 검증할 수 있게 지원하는 테스트 프레임워크
6) JSONassert: JSON용 어설션 라이브러리
7) JsonPath: JSON 데이터에서 특정 데이터를 선택하고 검색하기 위한 라이브러리

이 중 JUnit과 AssertJ를 가장 많이 사용한다.

1) JUnit

JUnit은 자바를 위한 단위 테스트 프레임워크이다.

  • 단위 테스트: 작성한 코드가 의도대로 작동하는지 작은 단위(메소드)로 검증하는 것

JUnit의 특징

1) 테스트 방식을 구분할 수 있는 어노테이션을 제공
2) @Test 어노테이션으로 메소드를 호출할 때 마다 새로운 객체를 생성(독립 테스트 가능)
3) 예상 결과를 검증하는 assert메소드 제공
4) 사용방법이 단순, 즉각적인 피드백 제공

1> JUnitTest.java 생성

test/java에 JUnitTest.java 생성

public class JUnitTest{
	@DisplayName("1 + 2는 3이다")
    @Test
    public void junitTest(){
    	int a = 1;
        int b = 2;
        int sum = 3;
        Assertions.assertEquals(sum, a+b);
    }

}

1) @DisplayName: 테스트 이름을 명시
2) @Test: 테스트를 수행하는 메소드라는 것을 명시, 테스트 할때마다 객체만들고 테스트 끝나면 객체를 삭제함.

2> JUnitCycleTest.java 생성

public class JUnitCycleTest{
	@BeforeAll
    static void beforeAll(){
    	System.out.println("@BeforeAll");
    }
    
    @BeforeEach
    public void beforeEach(){
    	System.out.println("@BeforeEach");
    }
    
    @Test
    static void test1(){
    	System.out.println("test1");
    }
    
    @Test
    static void test2(){
    	System.out.println("test2");
    }
    
    @Test
    static void test3(){
    	System.out.println("test3");
    }
    
    @AfterAll
    static void afterAll(){
    	System.out.println("@AfterAll");
    }
    
    @AfterEach
    public void afterEach(){
    	System.out.println("@AfterEach");
    }
}

1) @BeforeAll: 전체 테스트를 시작하기 전에 처음으로 한 번만 실행함.
ex> DB를 연결할 때, 테스트 환경을 초기화할 때
2) @BeforeEach: 테스트케이스를 실행하기 전에 매번 실행한다.
ex> 테스트 메소드에서 사용하는 객체를 초기화, 테스트에 필요한 값을 미리 넣어 사용
3) @AfterAll: 전체 테스트를 마치고 종료하기 전에 한 번만 실행함.
ex> DB연결을 종료할 때, 공통적으로 사용하는 자원을 해제할때
4) @AfterEach: 각 테스트 케이스를 종료하기 전 매번실행
ex> 테스트 이후 특정 데이터를 삭제할 때

  • static vs 그냥 public

    테스트 메소드 객체가 생성하기 전에 한번만 호출 -> static
    테스트 메소드 객체가 실행될때 마다 호출 -> 그냥 public

2) AssertJ

검증문의 가독성을 높여주는 라이브러리이다.

Assertions.assertEquals(sum, a+b);

위 코드는 명확하지 않아 가독성이 좋지 않다.

assertThat(a+b).isEqualTo(sum);

AssertJ를 통해 좋은 가독성을 가질 수 있다.

  • 자주사용하는 메소드
메소드 이름설명
isEqualTo(A)A값과 같은지 검증
isNotEqualTo(A)A값과 다른지 검증
contains(A)A값을 포함하는지 검증
doesNotContain(A)A값을 포함하지 않는지 검증
startsWith(A)접두사가 A인지 검증
endsWith(A)접미사가 A인지 검증
isEmpty()비어있는지 검증
isNotEmpty()비어있지 않은지 검증
isPositive()양수인지 검증
isNegative()음수인지 검증
isGreaterThan(1)1보다 큰값인지 검증
isLessThan(1)1보다 작은값인지 검증
isNotNull()NULL이 아닌지 검증
isZero()0인지 검증

테스트 코드 작성

1) TestControllerTest.java 생성

1> 환경설정

컨트롤러 클래스에 Alt+Enter를 눌러 CREATE TEST를 한다.

@SpringBootTest
@AutoConfigureMockMvc
class TestControllerTest{
	@Autowired
    protected MockMvc mockMvc;
    
    @Autowired
    private WebApplicationContext context;
    
    @Autowired
    private MemberRepository memberRepository
    
    @BeforeEach
    public void mockMvcSetUp(){
    	this.mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }
    
    @AfterEach
    public void cleanUp(){
    	memberRepository.deleteAll();
    }
}

1) @SpringBootTest: 이 어노테이션은 스프링 부트 애플리케이션의 전체 컨텍스트를 로드하여 통합 테스트를 수행하도록 설정한다. 이를 통해 실제 애플리케이션과 동일한 환경에서 테스트를 수행할 수 있다.


2) @AutoConfigureMockMvc: MockMvc를 생성하고 자동으로 구성한다.
MockMvc는 애플리케이션을 서버에 배포하지 않고도 테스트용 MVC환경을 만들어 요청, 전송, 응답 기능을 제공하는 유틸리티 클래스이다.(컨트롤러를 테스트할때 사용함)


3) @BeforeEach: 각 테스트 메소드 실행전에 MockMvc를 설정해준다.
4) @AfterEach: 각 테스트 메소드 종료전에 테이블에 있는 데이터를 모두 삭제한다.

2> 테스트 코드 작성

@DisplayName("getAllMembers: 아티클 조회에 성공한다.")
@Test
public void getAllMembers() throws Exception{
	//given
    final String url = "/test";
    Member savedMember = memberRepository.save(new Member(1L, "홍길동"));
    
    //when
    final ResultActions result = mockMvc.perform(get(url)
    .accept(MediaType.APPLICATION_JSON));
    
    //then
    result
    	.andExpect(status().isOk())
        .andExpect(jsonPath("$[0].id").value(savedMember.getId()))
        .andExpect(jsonPath("$[0].name").value(savedMember.getName()));
}

1) perform(): 요청을 전송하는 역할을 하는 메소드이다.
2) accept(): HTTP 요청 헤더에 Accept 헤더를 추가하여, 서버에게 응답을 어떤 형식으로 받아야 하는지 명시한다.(MediaType.APPLICATION_JSON은 서버가 JSON 형식으로 응답할 것을 기대한다는 것을 나타냄)
3) ResultActions 객체: 요청의 결과를 받는다. ReusltActions 객체는 반환값을 검증하고 확인하는 andExpect()메소드를 제공한다.
4) andExpect(): 응답을 검증한다. isOK(200)인지 확인한다.
5) jsonPath(): JSON 응답값의 결과를 가져오는 메소드이다. 0번째 배열에 들어있는 객체의 id와 name을 가져오고, 저장된 값과 같은지 확인한다.

0개의 댓글