교육 (Today I Learned)/Hanaro

[Hanaro] 54일차 / Spring Boot (Test)

Bay Im 2024. 4. 6. 12:27

Spring Boot Test

  • Test 관련 어노테이션
    • @SpringBootTest
      • 테스트 환경을 기본 설정해주는 어노테이션
    • @Test
      • 테스트할 메소드에 붙이는 어노테이션
    • @DisplayName(”메소드 이름”)
      • 해당 어노테이션에 메소드 이름을 적으면 콘솔에 출력된다.
    • @BeforeAll
      • 해당 메소드가 클래스 초기화시(테스트 실행 시 시작할 때) 한 번 수행되도록 하는 어노테이션
      • static 메소드로 생성 (static void 메소드명() {…})
    • @BeforeEach
      • 해당 메소드가 @Test 메소드를 호출시마다 한 번 수행되도록 하는 어노테이션
      • void 메소드명() {…}
  • 테스트 방법
    1. build.gradle에 아래 코드 추가
      • testCompileOnly 'org.projectlombok:lombok'
        testAnnotationProcessor 'org.projectlombok:lombok'
    2. test 폴더에 프로젝트이름ApplicationTests.java 기본 테스트 클래스가 있다.
    3. 위 클래스와 같은 폴더에 프로젝트이름ApplicationTests.java 클래스를 상속받은(extends) 테스트 클래스를 생성한다.
    4. 테스트할 Repository 클래스를 필드 주입한다. (테스트 클래스는 생성자 주입 안됨!)
      1. @Autowired MemberRepository memberRepository;
    5. 테스트할 메소드를 작성한다.
      1. public void 테스트메소드명() { … }
      2. 테스트 메소드에 @Test, @DisplayName(”테스트 메소드 이름”) 어노테이션을 붙인다.
      3. 메소드 안에는 테스트 할 로직 코드를 넣는다. (Repository나 Service 코드 같은)
    6. 추가로 @BeforeAll이나 @BeforeEach 어노테이션을 사용한 메소드도 작성할 수 있다.
    7. 위에서 작성한 해당 테스트 메소드 run 실행
  • Test 관련 함수
    • assertEquals()
      • 두 객체의 값이 같은지 확인하는 함수
      • assertEquals(기대 값, 실제 값, 실패시 출력할 콘솔메시지) 형태
      • 예시
        • *assertEquals*(3, list.size());
        • *assertEquals*("홍길동", unwrappedMemberEntity.getUserName());

 

  • 테스트 예시 코드
    • RepositoryTest
      • public class MemberRepositoryTest extends Ex12H2DbTestApplicationTests{
            // 필드 주입 (테스트 클래스는 생성자 주입안됨)
            @Autowired
            MemberRepository memberRepository;
        
            @BeforeAll  // static 메소드
            static void setup() {
                System.out.println("@BeforeAll - 클래스를 초기화시 한번 수행");
            }
        
            @BeforeEach
            void init() {
                System.out.println("@BeforeEach - @Test 메소드를 호출시마다 한번 수행");
                save();
            }
        
            @Test  // 테스트할 메소드에 사용
            @DisplayName("save 테스트")  // 콘솔에 출력되는 메소드 이름
            public void save() {
                memberRepository.save(new MemberEntity(Long.valueOf(1), "hong", "1234", "홍길동", "ROLE_USER", LocalDate.parse("2023-01-01")));
                memberRepository.save(new MemberEntity(Long.valueOf(2), "tom", "1234", "톰아저씨", "ROLE_USER", LocalDate.parse("2023-02-01")));
                memberRepository.save(new MemberEntity(Long.valueOf(3), "admin", "1234", "관리자", "ROLE_ADMIN", LocalDate.parse("2023-03-01")));
        
                List<MemberEntity> list = memberRepository.findAll();
        
                for (MemberEntity m: list) {
                    System.out.println(m.getUserName());
                }
        
                // 단정 함수(Assert Function)
                assertEquals(3, list.size());
            }
        
            @Test
            @DisplayName("findById 테스트")
            public void findById(){
                // Optional 클래스 : JDK 9부터 제공. null safety를 제공한다.
                Optional<MemberEntity> member = memberRepository.findById( 1L );
                member.ifPresent( unwrappedMemberEntity -> {
                    //null이 아닐때 수행되는 람다식
                    System.out.println( unwrappedMemberEntity.getUserName() );
                    assertEquals( "홍길동", unwrappedMemberEntity.getUserName() );
                });
                if( member.isPresent() ) {
                    String name = member.get().getUserName();
                    assertEquals( "홍길동", name );
                }else{
                    fail("member 값 가져오기 실패");
                }
            }
        
            @Test
            @DisplayName("count 테스트")
            public void count() {
                // SQL: SELECT COUNT(*) FROM member;
                Long count = memberRepository.count();
                System.out.println("count: " + count);
                assertEquals(3, count, "count 테스트 실패!");
            }
        
            @Test
            @DisplayName("쿼리메소드 테스트")
            public void query() {
                List<MemberEntity> list = memberRepository.findByUserId("tom");
                assertEquals(1, list.size());
                assertEquals("톰아저씨", list.get(0).getUserName());
        
                List<MemberEntity> list2 = memberRepository.findFirst5ByUserIdAndUserNameOrderByIdDesc("hong", "홍길동");
                assertEquals(1, list2.size());
        
                Boolean isExist = memberRepository.existsByJoindateLessThanEqual(LocalDate.now());
                System.out.println("isExist" + isExist);
        
                long count = memberRepository.countByUserNameIgnoreCaseLike("길");
                System.out.println("count: " + count);
            }
        
            @Test
            @DisplayName("JPQL 테스트")
            public void jpqlQuery() {
                List<MemberEntity> list = memberRepository.findByUserId_JPQL_Query("tom");
                assertEquals(1, list.size());
                assertEquals("톰아저씨", list.get(0).getUserName());
            }
        
            @Test
            @DisplayName("Native Query 테스트")
            public void nativeQuery(){
                List<MemberEntity> list =
                        memberRepository.findByUserId_nativeQuery("admin");
                assertEquals(1, list.size());
                assertEquals("관리자", list.get(0).getUserName());
            }
        
            @Test
            @DisplayName("update native SQL 테스트")
            public void update_nativeSql(){
                int result = memberRepository.updateById_nativeQuery(1L, "hong3");
                assertEquals(1, result);
        
                Optional<MemberEntity> member =
                        memberRepository.findById(1L);
                assertEquals("hong3", member.get().getUserId() );
            }
            
            // 1. member 테이블 안에 암호가 "1234"인 회원이 있는지 테스트 하시오.
            @Test
            @DisplayName("1. 암호가 1234 회원")
            public void pw1234() {
                List<MemberEntity> list = memberRepository.findByUserPwIsLike("1234");
        
        //        System.out.print("member 테이블 안에 암호가 \"1234\"인 회원: ");
        //        for (MemberEntity m: list) {
        //            System.out.print(m.getUserName() + " ");
        //        }
        //        System.out.println();
        
                assertEquals(0, list.size(), "암호가 1234인 회원이 존재합니다.");
            }
        
            // 2. 23년도 3월에 가입한 회원의 수가 1인지 테스트하시오.
            @Test
            @DisplayName("2. 23년도 3월에 가입한 회원")
            public void month3() {
                List<MemberEntity> list = memberRepository.findByJoindate_DayOfMonth(3);
        
        //        System.out.print("23년도 3월에 가입한 회원: ");
        //        for (MemberEntity m: list) {
        //            System.out.print(m.getUserName() + " ");
        //        }
        //        System.out.println();
        
                assertEquals(1, list.size());
            }
        
            // 3. "lee"라는 아이디로 회원가입하고자 할때, 아이디 중복인지 테스트하시오.
            @Test
            @DisplayName("3. lee 아이디 회원 확인")
            public void userIdLee() {
                List<MemberEntity> list = memberRepository.findByUserIdEquals("lee");
                assertEquals(0, list.size(), "해당 아이디가 존재합니다.");
            }
        
            // 4. "tom"이라는 아이디의 회원정보를 수정하고, 잘 수정되었는지 테스트하시오.
            //    톰아저씨 -> 마이클, 암호 -> 3456
            @Test
            @DisplayName("4. update tom")
            public void updateTom() {
                int result = memberRepository.updateByUserId_nativeQuery("tom", "마이클", "3456");
                assertEquals(1, result);
        
                Optional<MemberEntity> member =
                        memberRepository.findById(2L);
                System.out.println(member.get().getUserName() + ", " + member.get().getUserPw());
            }
        }
    • Repository
      • @Repository
        public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
            // SQL: select * from member where user_id = :userId;
            List<MemberEntity> findByUserId(String userId);
        
            // SQL: SELECT * FROM member where user_id = :userId AND user_name = :userName ORDER BY id DESC LIMIT 5;
            List<MemberEntity> findFirst5ByUserIdAndUserNameOrderByIdDesc(String userId, String userName);
        
            Boolean existsByJoindateLessThanEqual(LocalDate date);
            long countByUserNameIgnoreCaseLike(String userId);
        
            @Query(value="SELECT m FROM MemberEntity m WHERE m.userId = :userid")
            List<MemberEntity> findByUserId_JPQL_Query(String userid);
            
            @Query(value = "SELECT * FROM member WHERE user_id = :userid",
                    nativeQuery = true)
            List<MemberEntity> findByUserId_nativeQuery(String userid);
        
            @Modifying
            @Transactional
            @Query(value = "UPDATE member SET user_id = :userid where id = :id",
                    nativeQuery = true)
            int updateById_nativeQuery(Long id, String userid);
        
            // 연습 문제
            // 1. member 테이블 안에 암호가 "1234"인 회원이 있는지 테스트 하시오.
            List<MemberEntity> findByUserPwIsLike(String userPw);
        
            // 2. 23년도 3월에 가입한 회원의 수가 1인지 테스트하시오.
            @Query(value = "SELECT * FROM member WHERE MONTH(joindate) = :month", nativeQuery = true)
            List<MemberEntity> findByJoindate_DayOfMonth(int month);
        
            // 3. "lee"라는 아이디로 회원가입하고자 할때, 아이디 중복인지 테스트하시오.
            List<MemberEntity> findByUserIdEquals(String userid);
        
            // 4. "tom"이라는 아이디의 회원정보를 수정하고, 잘 수정되었는지 테스트하시오.
            //    톰아저씨 -> 마이클, 암호 -> 3456
            @Modifying
            @Transactional
            @Query(value = "UPDATE member SET user_name = :username, user_pw = :userpw" +
                    " where user_id = :userid",
                    nativeQuery = true)
            int updateByUserId_nativeQuery(String userid, String username, String userpw);
        }
728x90