테스트 작성하기

OneTwoThree·2022년 10월 20일
0

유튜브

서비스의 동작을 확인하기 위해 테스트코드를 작성해보자

테스트란 ?

프로그램의 품질 검증을 위한 것
의도대로 프로그램이 동작하는지 확인
일일히 요청 보내고 응답 하고 하는 테스트 과정을 최소화

3단계로 구성

  • 예상 시나리오 작성, 실제 코드 결과와 비교, 검증
  • 통과 : 더 좋은 코드로 리팩토링
  • 실패 : 디버그를 통해 코드 고쳐준다

다양한 상황에 맞춰 테스트 케이스를 작성

테스트를 통한 코드 검증, 리팩토링이 중요하다

TDD

테스트코드를 먼저 만들고 코드를 점진적으로 코드를 개선, 확장하는 방법


원하는 메소드로 가서 우클릭하고 generate > test 해준다
라이브러리 설치 안되어있다고 Fix 떠서 설치함

test 폴더 안에 ArticleServiceTest 클래스가 생기고 여기에 테스트 코드가 생성됨

package com.example.firstproject.service;

import com.example.firstproject.entity.Article;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest // 해당 클래스는 스프링부트와 연동되어 테스트됨
class ArticleServiceTest {

    @Autowired ArticleService articleService;

    @Test
    void index() {
        // 예상
        Article a = new Article(1L, "aaaa", "1111");
        Article b = new Article(2L, "bbbb", "2222");
        Article c = new Article(3L, "cccc", "3333");
        List<Article> expected = new ArrayList<Article>(Arrays.asList(a,b,c));


        // 실제
        List<Article> articles =articleService.index();

        // 비교
        assertEquals(expected.toString(), articles.toString());
    }
}

테스트 클래스 내부에 index를 테스트하기 위해 만들었다.
먼저 클래스 위에 @SpringBoot 어노테이션을 넣어서 스프링부트와 연동되어 테스트되게 했다
그리고 서비스 클래스를 @Autowired 어노테이션으로 DI해서 가져왔다.

예상 데이터 (data.sql에 내가 만들어놓은 Article의 리스트) 와 실제 데이터 (실제 index 메소드 호출결과) 를 비교해준다.

화살표 눌러서 테스트해주면 된다..

이렇게 테스트 성공을 확인할 수 있다.

의도적으로 예상 데이터 3번째 아티클의 id를 4로 바꿔서 테스트가 틀리게 해보자.

이렇게 테스트가 실패하고 기대값과 실제값까지 보여준다.

    @Test
    void show_성공____존재하는_id_입력() {
        //예상
        Long id = 1L;
        Article expected = new Article(id,"aaaa","1111");

        //실제
        Article article = articleService.show(id);

        //비교
        assertEquals(expected.toString(),article.toString());
    }

    @Test
    void show_실패____존재하지_않는_id_입력() {
        //예상
        Long id = -1L;
        Article expected = null;

        //실제
        Article article = articleService.show(id);

        //비교 null은 toString을 호출할 수 없으니까 지워주자
        assertEquals(expected,article);

    }

show 는 이런식으로 경우를 나눠서 테스트했다.
존재하지 않는 id를 입력하는 경우에 show는 null을 반환한다.
따라서 expected도 null로 넣는다
마지막에 assertEquals로 비교할 때 null은 toString이 없으니까 지워줘야 한다.

    @Test
    void create_성공____title과_content만_있는_dto_입력() {
        //예상
        String title = "라라라라";
        String content = "4444";
        ArticleForm dto = new ArticleForm(null,title,content);
        Article expected = new Article(4L,title,content);

        //실제
        Article article = articleService.create(dto);

        //비교
        assertEquals(expected.toString(),article.toString());
    }

    @Test
    void create_실패____id가_포함된_dto_입력() {
        //예상
        String title = "라라라라";
        String content = "4444";
        ArticleForm dto = new ArticleForm(4L,title,content);
        Article expected = null;

        //실제
        Article article = articleService.create(dto);

        //비교
        assertEquals(expected,article);
        
    }

create 테스트하는 코드. 내용은 거의 비슷하다.

여기까지 다 테스트 작동해보면 잘 된다.

이제 클래스를 이용해서 전체 메소드를 한번에 테스트해보자.

그런데 한번에 묶어서 테스트하니까 index가 실패한다.
이유는 create 할때 데이터를 하나 만드는데 그것때문에 예상결과와 실제결과가 달라진것이다.
이를 해결하기 위해 테스트를 위한 트랜잭션을 해줘야 한다.

package com.example.firstproject.service;

import com.example.firstproject.dto.ArticleForm;
import com.example.firstproject.entity.Article;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest // 해당 클래스는 스프링부트와 연동되어 테스트됨
class ArticleServiceTest {

    @Autowired ArticleService articleService;

    @Test
    void index() {
        // 예상
        Article a = new Article(1L, "aaaa", "1111");
        Article b = new Article(2L, "bbbb", "2222");
        Article c = new Article(3L, "cccc", "3333");
        List<Article> expected = new ArrayList<Article>(Arrays.asList(a,b,c));


        // 실제
        List<Article> articles =articleService.index();

        // 비교
        assertEquals(expected.toString(), articles.toString());
    }

    @Test
    void show_성공____존재하는_id_입력() {
        //예상
        Long id = 1L;
        Article expected = new Article(id,"aaaa","1111");

        //실제
        Article article = articleService.show(id);

        //비교
        assertEquals(expected.toString(),article.toString());
    }

    @Test
    void show_실패____존재하지_않는_id_입력() {
        //예상
        Long id = -1L;
        Article expected = null;

        //실제
        Article article = articleService.show(id);

        //비교 null은 toString을 호출할 수 없으니까 지워주자
        assertEquals(expected,article);

    }


    @Test
    @Transactional
    void create_성공____title과_content만_있는_dto_입력() {
        //예상
        String title = "라라라라";
        String content = "4444";
        ArticleForm dto = new ArticleForm(null,title,content);
        Article expected = new Article(4L,title,content);

        //실제
        Article article = articleService.create(dto);

        //비교
        assertEquals(expected.toString(),article.toString());
    }

    @Test
    @Transactional
    void create_실패____id가_포함된_dto_입력() {
        //예상
        String title = "라라라라";
        String content = "4444";
        ArticleForm dto = new ArticleForm(4L,title,content);
        Article expected = null;

        //실제
        Article article = articleService.create(dto);

        //비교
        assertEquals(expected,article);

    }


}

데이터 조회가 아닌 생성, 삭제, 수정 등을 테스트 할 때는 트랜젝션 어노테이션을 붙여줘야 한다.

이렇게 트랜잭션 처리를 해주니까 모두 통과했다.

21강 23분부터 테스트 자율 과제!


요약

  • ArticleService에 있는 CRUD 메소드를 테스트해봤다
  • 테스트 디렉토리 안에 같은 패키지 안에 테스트코드가 생긴다
  • 스프링부트와 연동된 테스트를 위해 @SpringBootTest
  • 테스트 진행은 예상, 실제, 비교로 진행된다
  • 성공하는 경우, 실패하는 경우의 테스트가 존재함 , 성공, 실패 역시 나눠서 테스트할 수 있다.

0개의 댓글