* 테스트 코드 작성 → 본 코드 작성 *
이렇게 코드를 짜는게 좋지만 지금 당장 테스트부터 하긴 어려우니까 나중에 공부 많이하고나서 해보자.
지금은 본코드 → 테스트 코드 → 본코드 수정 이렇게!!
단위 테스트하는 이유 : 가볍고 빠르게 테스트하기 위해
핵심 : 메모리에 전체 프로젝트를 올리지 않고 필요한 것만 올려야한다.
폴더 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
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9