SpringBoot with JPA CRUD 테스트

mingki·2022년 1월 26일
0

SpringBoot & JPA

목록 보기
8/26
post-thumbnail

📚 공부한 책 : 코드로배우는 스프링 부트 웹프로젝트

1.JpaRepository 인터페이스

Spring Data JPA 에는 여러 종류의 인터페이스의 기능을 통해 JPA관련 작업을 별도의 코드 없이 처리할 수 있도록 지원한다
ex) CRUD작업,페이징,정렬 등을 인터페이스의 메서드를 호출하는 형태로 처리한다 (기능에 따라 상속 구조로 추가적인 기능을 제공한다)

  • JpaRepository 인터페이스 : 모든 JPA 관련 기능을 사용하고 싶을때 이용한다
    아래와 같이 JPA 인터페이스를 생성한다
import com.example.entity.Memo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
// JPA를 사용할 때는 엔티티의 타입정보(Memo)와 @Id 타입(Long)을 지정한다
// JPA는 인터페이스 선언만으로도 자동으로 스프링의 빈(Bean)으로 등록된다
public interface MemoRepository extends JpaRepository<Memo,Long> {												
}

2.테스트코드를 통한 CRUD 연습

위에서 작성한 MemoRepository를 이용해 작성된 테이블에 SQL없이 CRUD테스트를 진행한다 (다음과 같은 메서드를 활용한다)

  • insert : save(entity 객체)
  • select : findById(키 타입),getOne(키 타입)
  • update : save(entity 객체)
  • delete : deleteById(키 타입),delete(entity 객체)
    ◆ insert 와 update는 동일한 메서드를 사용한다 -> save()
    => JPA의 구현체가 메모리상에서 객체를 비교하고 없으면 insert 존재한다면 update를 동작시키는 방식으로 동작하기 때문이다

3.테스트 클래스 생성

테스트 클래스를 아래와 같이 생성한다

import com.example.entity.Memo;
import com.example.repository.MemoRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
import java.util.stream.IntStream;
@SpringBootTest
public class MemberRepositoryTest {
    @Autowired
    MemoRepository memoRepository;
    @Test
    public void testInsert(){
    // getClass() 메소드는 MemoRepository 인터페이스 타입의 실제 객체가 어떤것인지 확인한다
        System.out.println(memoRepository.getClass().getName());
    }   
}

★ testInsert() 를 실행했을 때 아래와 같은 오류가 발생했고 해결하는데 한참걸렸다 해결방법은 간단했다

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.ex2.repository.MemberRepositoryTest': Unsatisfied dependency expressed through field 'memoRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.repository.MemoRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: 

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.repository.MemoRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1799) ~[spring-beans-5.3.15.jar:5.3.15]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1355) ~[spring-beans-5.3.15.jar:5.3.15]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.15.jar:5.3.15]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.15.jar:5.3.15]
	 76 common frames omitted

★ 아래와 같이 메인 Application 클래스에서 @EnableJpaRepositories("com.example") 를 추가해주니 해결되었다

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EntityScan("com.example")
@EnableJpaRepositories("com.example")

public class Ex2Application {

	public static void main(String[] args) {
		SpringApplication.run(Ex2Application.class, args);
	}

}

3-1 insert 테스트

테스트 코드 작성

@SpringBootTest
public class MemberRepositoryTest {
    @Autowired
    MemoRepository memoRepository;
    // 등록
    @Test
    public void testInsertDummies(){
    // 100개의 새로운 Memo객체를 생성하고 
        IntStream.rangeClosed(1,100).forEach(i -> {
           Memo memo =  Memo.builder().memoText("Memo..." + i).build();			
            // 저장한다
           memoRepository.save(memo);
        });
    }
}

☀︎ 테스트 실행결과 아래와같이 DB에 100개의 Memo가 생성된것을 확인할 수 있다

3-2 조회 테스트

테스트 코드 작성

@SpringBootTest
public class MemberRepositoryTest {
    @Autowired
    MemoRepository memoRepository;
	//조회
    @Test
    public void testSelect(){
        Long mno = 100L;
        Optional<Memo> result = memoRepository.findById(mno);
        System.out.println("================");
        if(result.isPresent()){
            Memo memo = result.get();
            System.out.println(memo);
        }
    }
}

☀︎ 테스트 실행결과 아래와같이 DB에 100개의 Memo가 생성된것을 확인할 수 있다

  • findByld( )의 경우 java.util 패커지의 Optional 타입으로 반환되기 때문에 한번 더 결과 가 존재하는지를 체크히는 형태로 작성하게 된다
Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
================
Memo(mno=100, memoText=Memo...100)

3-3 update 테스트

테스트 코드 작성

import com.example.entity.Memo;
import com.example.repository.MemoRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
import java.util.stream.IntStream;
@SpringBootTest
public class MemberRepositoryTest {
    @Autowired
    MemoRepository memoRepository;
    @Test
    public void testUpdate(){
        // 객체 생성
        Memo memo = Memo.builder().mno(1L).memoText("Update Text......").build();
        System.out.println("1-------------");
        memoRepository.save(memo);
        System.out.println("2-------------");
    }
}

♡ 실행 쿼리

  • JPA는 엔티티 객체들을 메모리상에 보관하려고 하기 때문에 특정한 엔티티 객체가 존재 하는지 확인하는 select가 먼저 실행되고 해당 @Id를 가진 엔티티 객체가 있다면 update, 그렇지 않다면 insert를 실행하게 된다
1-------------
Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
Hibernate: 
    update
        tbl_memo 
    set
        memo_text=? 
    where
        mno=?
2-------------

☀︎ 테스트 실행결과 아래와같이 mno 1번의 memoText가 변경된것을 확인할 수 있다

3-4 delete 테스트

테스트 코드 작성

import com.example.entity.Memo;
import com.example.repository.MemoRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
import java.util.stream.IntStream;
@SpringBootTest
public class MemberRepositoryTest {
    @Autowired
    MemoRepository memoRepository;
    @Test
    public void testDelete(){
        Long mno = 5L;
        memoRepository.deleteById(mno);
    }
}

♡ 실행 쿼리

Hibernate: 
    select
        memo0_.mno as mno1_0_0_,
        memo0_.memo_text as memo_tex2_0_0_ 
    from
        tbl_memo memo0_ 
    where
        memo0_.mno=?
Hibernate: 
    delete 
    from
        tbl_memo 
    where
        mno=?

☀︎ 테스트 실행결과 아래와같이 mno 5번 데이터가 삭제된 것을 확인할 수 있다

profile
비전공초보개발자

0개의 댓글