Loading...

Spring / / 2022. 5. 27. 14:12

Junit5 Repository 테스트 @DataJpaTest

반응형

 

* 테스트 코드 작성 → 본 코드 작성 *


이렇게 코드를 짜는게 좋지만 지금 당장 테스트부터 하긴 어려우니까 나중에 공부 많이하고나서 해보자.

지금은 본코드 → 테스트 코드 → 본코드 수정 이렇게!!

단위 테스트하는 이유 : 가볍고 빠르게 테스트하기 위해


핵심 : 메모리에 전체 프로젝트를 올리지 않고 필요한 것만 올려야한다.



폴더 3개 만들어두고 테스트 폴더 안에도 똑같은 구조로 폴더 만들어주기

 



본 코드 작성할 때 항상 1번은 domain 부터!

데이터베이스의 ERD가 만들어졌다면 자바에 똑같이 UML이 나온다.
ERD는 FK로 연결되고, UML은 ORM 오브젝트를 연결해준다.


ORM(Object Relational Mapping)을 쓰면 객체지향적인 프로그래밍을

데이터베이스의 영향을 받지 않고 할 수 있다.

null 처리하기 쉽게 래핑 타입을 사용하자.

 

@Getter
@Entity
public class Book {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private Long id;
    private String title;
    private String author;
}


이 모델은 데이터베이스와 통신하는 Dto라 해서 VO(Value Object)라고 한다.
Dto는 클라이언트와 통신하는 모델!

 



엔티티에 데이터가 들어올때는

 

1. 클라이언트한테 데이터를 받아와서 DB에 save 할 때
2. DB에서 SELECT 해 올 때

우리가 직접 코드를 작성해서 데이터를 집어넣을때는 1번이다.

2번은 jpa가 알아서 넣어주니까!

id를 우리가 직접 set 하여 값을 넣어줄 일이 없기 때문에 @Setter를 만들어주지 않는다.

마찬가지로 id를 set 해줄일이 죽어도 없기 때문에 풀생성자도 만들지 않는다.


그리고 디폴트 생성자도 쓸일이 없기 때문에 없애준다.

 

필요없는건 안만들어줘!

 

필요한 생성자만 만들어줄건데
생성자를 쓸 때 순서에 맞게 파라미터를 넣어줘야하는 단점이 있다.


이때는 빌더를 사용하면 좋다.

 

@Builder
public Book(Long id, String title, String author) {
    this.id = id;
    this.title = title;
    this.author = author;
}


근데 빌더 안쓰고 필요한 생성자만 만들어주자
그리고 Setter는 미리 만들지 않고 필요할 때 만들자.

 

@Getter
@Entity
public class Book {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private Long id;
    private String title;
    private String author;

    @Builder
    public Book(Long id, String title, String author) {
        this.id = id;
        this.title = title;
        this.author = author;
    }
}



레파지토리 테스트 : CRUD가 잘되는지 테스트
본코드에 컨트롤러 만들어서 테스트 하지말고 테스트 코드 작성하자.


@DataJpaTest

런타임시에 JVM이 어노테이션을 확인하고 분석 → 메모리에 띄우기 (리플렉션)
→ DB관련된 컴포넌트만 메모리에 로딩(레파지토리, 영속성컨텍스트 등등)

이 어노테이션은 기본적으로 인메모리 데이터베이스를 사용하여 h2가 동작한다.


내부에 @Transactional이 걸려있기 때문에 자동 롤백을 해준다.

 


junit은 스프링 프로젝트와 별개로 자기만의 프록시를 하나 만든다. 자기만의 공간.

프로젝트가 가지고 있는 것들을 메모리에 띄울 필요가 없는것이다.

 

@DataJpaTest는 스프링 컨테이너로 들어가서 필요한걸 junit 공간에 띄워야 하는데

스프링 컨테이너로 들어가기 위해 걸어주는 어노테이션이 @ExtendWith이다.

해당 클래스를 메모리에 띄울때 DI 하려고

@RequiredArgsConstructor를 붙이고 생성자에 주입해주기 위해서는

IoC 컨테이너에 등록되어 있어야 찾아서 넣어준다.


근데 스프링이 메모리에 띄운게 아니라 junit이 띄운 애한테는 생성자를 주입해주지 못한다.


그래서 이 때 @Autowired를  걸어준다.

 

얘도 DI를 해주는데 이건 스프링이 리플렉션으로 주입해준다.

생성자로 주입해주는게 아니라!!

 


 

테스트 메서드 실행순서는 가늠할 수 없다.


그래서 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)을 붙여주고
메서드마다 @Order(1), @Order(2)를 붙여주어 순서를 지정해 줄 수 있다.

 

클래스 단위로 테스트가 종료될 때 롤백되기 때문에 auto_increment 초기화 문제가 해결되지 않는다.
그래서 우리는 각 메서드가 실행되기 전마다 수행되는 메서드 이전에 실행되는 @BeforeEach를 써줄것이다.

각각 메서드가 실행되기 이전에 id값을 초기화해주는것이다.

 

@BeforeEach
public void db_init() {
    // 데이터베이스 초기화
    bookRepository.deleteAll();
    em
            .createNativeQuery("ALTER TABLE book ALTER COLUMN id RESTART WITH 1")
            .executeUpdate();
}

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 
반응형