1. JUnit이란?
JUnit은 자바 프로그래밍 언어를 위한 유닛 테스트 프레임워크이다. 유닛 테스트는 소프트웨어의 개별적인 구성 요소인 유닛(일반적으로 클래스 또는 메서드)이 올바르게 동작하는지를 확인하는 테스트 방법이다.
커피 머신을 테스트 한다. 그림의 커피 머신은 두 가지 기능을 수행한다. 하나의 모듈은 커피콩을 1cm 크기로 가는 역할, 다른 모듈은 1cm 로 갈아버린 커피 가루를 받아서 커피를 뽑아낸다.
머신 테스트 하는 과정은 다음과 같다.
- 테스트를 하려면 모듈화 - 책임 분리
- 테스트는 격리되어 있어야 한다. 가짜 데이터를 활용해서 테스트
- 테스트는 모든 예외들을 테스트 해봐야 한다. 잘된 경우가 아니라 오류도 테스트 해야 한다. 완벽할 순 없다.
- 통합 테스트. 연결해서 테스트. 격리 상태에서 잘되면 통합 테스트는 잘됨
- 문제는 내부 모듈 중 하나가 변경 되었을 때 통합하면 문제가 발생함. 그래서 격리된 채로 통합 테스트 코드로 테스트를 해봐야됨.
- 통합 테스트는 유기적으로 발생한 문제를 잡을 수 있음.
2. JUnit을 활용한 테스트
테스트를 위해 test폴더에 board/BoardRepositoryTest를 만든다. 파일을 만들 때 테스트할 클래스와 위치를 같게 만들어주는게 좋다.
테스트를 위해서 해당 어노테이션이 필요하다.
테스트를 위한 더미데이터
insert into board_tb(title, content, author) values('제목1', '내용1', '홍길동'); insert into board_tb(title, content, author) values('제목2', '내용2', '홍길동'); insert into board_tb(title, content, author) values('제목3', '내용3', '장보고'); insert into board_tb(title, content, author) values('제목4', '내용4', '장보고'); insert into board_tb(title, content, author) values('제목5', '내용5', '장보고'); insert into board_tb(title, content, author) values('제목6', '내용6', '장보고'); insert into board_tb(title, content, author) values('제목7', '내용7', '임꺽정'); insert into board_tb(title, content, author) values('제목8', '내용8', '임꺽정');
테스트는 Given, When, Then 순으로 진행된다. Given 은 가짜 데이터 삽입, When 은 테스트할 코드 실행, Then 은 결과를 출력한다.
2.1 SelectOne
board/BoardRepository
public Board selectOne(int id){ Query query = em.createNativeQuery("select * from board_tb where id=?",Board.class); query.setParameter(1,id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null ; } }
board_tb 에서 하나의 테이블만 조회한다.
test/java/shop.mtcoding/blog/board/BoardRepositoryTest
public void select_test(){ //given int id =1; //when Board board = boardRepository.selectOne(id); //then. 20이 들어오면 컨트롤러가 아니라 레파지토리 책임, 상태 검사 객체의 필트 System.out.println(board); Assertions.assertThat(board.getTitle()).isEqualTo("제목1"); Assertions.assertThat(board.getContent()).isEqualTo("내용1"); Assertions.assertThat(board.getAuthor()).isEqualTo("홍길동"); }
임의의 데이터 int id =1; 를 입력해 테스트해본다.
데이터가 조회된다. 만약
isEqualTo
에 데이터를 다르게 입력한다면 오류가 발생한다.2.2 selectAll
board/BoardRepository
public List<Board> selectAll(){ Query query = em.createNativeQuery("select * from board_tb",Board.class); List<Board> boardList = query.getResultList(); // 테스트 하려면 더미데이터 없이 테스트 해봐야됨. 데이터가 없을 때 어떻게 되는지. // //더미데이터가 0이면 boardList 의 사이즈는 0. 빈 컬렉션을 리턴. return boardList ; }
전체 테이블을 조회하게 되면 List 타입으로 받아야 한다.
test/java/shop.mtcoding/blog/board/BoardRepositoryTest
@Test public void selectAll_test(){ //given //when List<Board> boardList = boardRepository.selectAll(); //then System.out.println(boardList.size()); //더미데이터가 0이면 boardList 의 사이즈는 0. 빈 컬렉션을 리턴. Assertions.assertThat(boardList.get(0).getTitle()).isEqualTo("제목1"); Assertions.assertThat(boardList.get(0).getContent()).isEqualTo("내용1"); Assertions.assertThat(boardList.get(0).getAuthor()).isEqualTo("홍길동"); Assertions.assertThat(boardList.size()).isEqualTo(8);
전체 데이터의 크기를 알 수 있다.
2.3 Insert
board/BoardRepository
@Transactional public void insert(String title, String content, String author){ Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, title); query.setParameter(2, content); query.setParameter(3, author); query.executeUpdate(); }
test/java/shop.mtcoding/blog/board/BoardRepositoryTest
@Test public void insert_test(){ // 테스트 메서드는 파라미터를 적을 수 없음. 리턴도 없음. //given 가짜 데이터 넣기 String title ="제목10"; String content = "내용10"; String author = "이순신"; //when boardRepository.insert(title,content,author); //then 확인 List<Board> boardList = boardRepository.selectAll(); System.out.println(boardList.size()); }
selectOne()
로 전체 데이터를 받아 결과를 확인한다. 데이터를 추가하면 전체 크기를 조회했을 때 9가 된다.2.4 Delete
board/BoardRepository
@Transactional public void delete(int id){ Query query = em.createNativeQuery("delete from board_tb where id =?"); query.setParameter(1,id); query.executeUpdate(); }
test/java/shop.mtcoding/blog/board/BoardRepositoryTest
@Test public void delete_test(){ //given int id1 =1 ; int id2 = 2; //when boardRepository.delete(id1); //then Board board1 = boardRepository.selectOne(id1); Board board2 = boardRepository.selectOne(id2); List<Board> boardList = boardRepository.selectAll(); System.out.println(board1); System.out.println(board2); System.out.println(boardList.size()); }
삭제하면 데이터를 조회했을 때 null 값이 조회되고, 전체 크기도 7로 줄어든다.
2.5 Update
Update 는 3가지가 있는데 각각의 메서드를 만든다. 내용은 동일하기 때문에 하나만 적는다.
board/BoardRepository
@Transactional public void updateTitle(String title,int id){ Query query = em.createNativeQuery("update board_tb set title =? where id =?"); query.setParameter(1,title); query.setParameter(2,id); query.executeUpdate(); }
test/java/shop.mtcoding/blog/board/BoardRepositoryTest
@Test public void updateTitle_test(){ //given; String title = "수정1"; int id = 1; //when boardRepository.updateTitle(title,id); //then Board board = boardRepository.selectOne(id); System.out.println(board); Assertions.assertThat(board.getTitle()).isEqualTo("수정1"); }
Share article