BookRepositoryTest - 책 수정하기

jihan kong·2022년 8월 26일
0

JUnit5

목록 보기
9/25
post-thumbnail

본 시리즈는 메타 코딩님의 Junit 강의를 학습한 내용을 바탕으로 정리하였습니다.

CRUD의 마지막... Update가 남아있다. 사실 웹 개발을 하면서 수 많은 CRUD를 해보았고, 많이 익숙한 개념이다. 그렇지만 익숙하다고 해서 그것이 중요하지 않은 것은 아니다. 가장 기본이자 가장 핵심이 되는 내용이 REST API이기 때문에 이를 몇번이고 반복해서 학습하며 기반을 잘 닦아놓아야 이를 토대로 여러 가지 다른 재밌는 일들을 할 수 있다고 생각한다.

(각설하고)


책 수정_test()

BookRepository.java

@DataJpaTest 
public class BookRepositoryTest {

    @Autowired 
    private BookRepository bookRepository;

    @BeforeEach // 각 테스트 시작전에 한번씩 실행
    public void 데이터준비() {
        String title = "junit5";
        String author = "메타코딩";
        Book book = Book.builder()
            .title(title)
            .author(author)
            .build();
        bookRepository.save(book);
    }
    
    // 1. 책 등록
    // 2. 책 목록보기
    // 3. 책 한건 보기
    // 4. 책 삭제
    // ...(생략)
    
    // 5. 책 수정
    @Sql("classpath:db/tableIni.sql")
    @Test
    public void 책수정_test() {
        // given    
        Long id = 1L;
        String title = "Junit";			// 1.
        String author = "겟인데어";	    // 1.
        
        Book book = new Book(id, title, author);

		// when
        Book bookPS = bookRepository.save(book);

        // then
        assertEquals(id, bookPS.getId());
        assertEquals(title, bookPS.getTitle());
        assertEquals(author, bookPS.getAuthor());
    }
  1. 데이터 수정을 위해 새로운 데이터( Junit, 겟인데어 ) 를 삽입한다.

그런데 신기한 점이 있다. 실제로 DB에 반영할 업데이트에 관한 쿼리를 하나도 만들지 않았는데 어떻게 titleauthor 의 내용만 가지고 업데이트가 반영될까?

다음에 해답이 있다.

더티체킹(Dirty checking)

💡 더티 체킹이란?
데이터의 값을 변경하면 트랜잭션이 끝나는 시점에 해당 테이블에 변경분을 반영하는 것을 말한다. 즉, Entity 객체의 값만 변경하면 별도로 Update 쿼리를 날릴 필요가 없는 것이다.

이 개념으로 인해 책 수정 테스트를 이대로 완료해도 괜찮지만 그래도 직접 확인을 하는 것이 좋기에 눈으로 확인할 수 있게끔 테스트를 변경해보자.


BookRepositoryTest.java

    // 4. 책 수정
    @Sql("classpath:db/tableIni.sql")
    @Test
    public void 책수정_test() {
        // given
        Long id = 1L;
        String title = "Junit";
        String author = "겟인데어";
        Book book = new Book(id, title, author);
        
 		// when
 		bookRepository.findAll().stream()
        	.forEach(b) -> {
                System.out.println(b.getId());
            	System.out.println(b.getTitle());
             	System.out.println(b.getAuthor());
				System.out.println("1. ==================");
		});
                
        Book bookPS = bookRepository.save(book);
 
        bookRepository.findAll().stream()
        	.forEach((b) -> {
             	System.out.println(b.getId());
             	System.out.println(b.getTitle());
             	System.out.println(b.getAuthor());
     		 	System.out.println("2. ==================");
         });
         
         System.out.println(bookPS.getId());
         System.out.println(bookPS.getTitle());
         System.out.println(bookPS.getAuthor());
         System.out.println("3. ==================");
}

위 테스트로 예상할 수 있는 출력 로그는 다음과 같고, 그 아래는 이에 대한 해석이다.

1. ==================

null

2. ==================

1
Junit
겟인데어

3. ==================

1
Junit
겟인데어

1

: 책 수정 테스트 시작 전에 실행되는 @BeforeEach 데이터 준비 메소드의 내용이 @Sql("classpath:db/tableIni.sql") 문에 의해 모두 삭제되어 null 값이 될 것이다.

2

: Book bookPS = bookRepository.save(book); 에 의해 새롭게 save 가 된 상태이다. 값이 변경된 상태이기 때문에 업데이트가 일어났을 것이고, 따라서 Junit, 겟인데어 가 출력되었을 것이다.

3

: 업데이트가 반영된 이후의 데이터 내용을 출력했을 것이므로 2의 내용이 그대로 출력되었을 것이다.


실제 전체 테스트를 돌려보면...

뭔가 이상하다. 분명히 테이블을 새로 만드는 쿼리를 날렸는데 @BeforeEach 의 내용이 남아있다.. 왜일까? (아래의 의문점❓ 참조)

이 외에는 우리가 기대한 값이 잘 출력되었다.


의문점❓

위에서 본 것처럼 책 수정 테스트에 한 가지 의문점이 발생한다. 전에 언급된 트랜잭션의 실행 흐름은 다음과 같다.

이렇게 하나의 세트처럼 움직이게 되고 책 수정 테스트를 시작할 때는 @Sql("classpath:db/tableIni.sql") 어노테이션이 붙어있다.

즉,

@Sql("classpath:db/tableIni.sql") 쿼리를 통해 테이블을 모두 날리는 작업이 분명히 진행되게 된다. 그런데 왜 테스트 진행시 @BeforeEach 에서 삽입된 값이 삭제되지 않고 위에서 본 것 처럼 이렇게

1. ==================

1
Junit5
메타코딩

남아있을까?

이에 대한 내용은 다음 포스팅에서...

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글