Part 9. 비즈니스 계층
9.2 비즈니스 계층의 구현과 테스트
- BoardMapper와 BoardService, BoardServiceImpl에 대한 구조 설정이 완료되었으므로 'src/test/java' 밑에 org.zerock.service.BoardServiceTests 클래스를 작성해 테스트 작업을 진행한다.
< BoardServiceTests 클래스 >
package org.zerock.service;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
// Java Config
// @ContextConfiguration(classes = {org.zerock.config.RootConfig.class})
@Log4j
public class BoardServiceTests {
@Setter(onMethod_ = {@Autowired })
private BoardService service;
@Test
public void testExist() {
log.info(service);
assertNotNull(service);
}
}
- BoardServiceTests의 첫 테스트는 BoardService 객체가 제대로 주입이 가능한지 확인하는 작업으로 시작한다.
- 정상적으로 BoardService 객체가 생성되고 BoardMapper가 주입되었다면 아래와 같이 BoardService 객체와 데이터베이스 관련 로그가 같이 출력된다.
INFO : org.zerock.service.BoardServiceTests - org.zerock.service.BoardServiceImpl@64693226
INFO : org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@65b3f4a4: startup date [Wed Aug 09 22:21:26 KST 2023]; root of context hierarchy
INFO : com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
INFO : jdbc.connection - 1. Connection closed
INFO : jdbc.audit - 1. Connection.close() returned
INFO : jdbc.connection - 2. Connection closed
INFO : jdbc.audit - 2. Connection.close() returned
INFO : jdbc.connection - 3. Connection closed
INFO : jdbc.audit - 3. Connection.close() returned
INFO : jdbc.connection - 4. Connection closed
INFO : jdbc.audit - 4. Connection.close() returned
INFO : jdbc.connection - 10. Connection opened
INFO : jdbc.audit - 10. Connection.new Connection returned
INFO : jdbc.connection - 5. Connection closed
INFO : jdbc.audit - 5. Connection.close() returned
INFO : jdbc.audit - 10. Connection.setReadOnly(false) returned
INFO : jdbc.audit - 10. Connection.setAutoCommit(true) returned
INFO : jdbc.connection - 6. Connection closed
INFO : jdbc.audit - 6. Connection.close() returned
INFO : jdbc.connection - 7. Connection closed
INFO : jdbc.audit - 7. Connection.close() returned
INFO : jdbc.connection - 8. Connection closed
INFO : jdbc.audit - 8. Connection.close() returned
INFO : jdbc.connection - 9. Connection closed
INFO : jdbc.audit - 9. Connection.close() returned
INFO : jdbc.connection - 10. Connection closed
INFO : jdbc.audit - 10. Connection.close() returned
INFO : com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.
9.2.1 등록 작업의 구현과 테스트
- 등록 작업은 BoardServiceImpl에서 파라미터로 전달되는 BoardVO 타입의 객체를 BoardMapper를 통해 처리한다.
- 구현되는 코드는 아래와 같다.
< BoardServiceImpl 클래스 >
@Override
public void register(BoardVO board) {
log.info("register......" + board);
mapper.insertSelectKey(board);
}
- BoardService는 void 타입으로 설계되었으므로 mapper.insertSelectKey()의 반환 값인 int를 사용하지 않고 있지만, 필요하다면 예외 처리나 void 대신에 int 타입을 이용해 사용할 수 있다.
- mapper의 insertSelectKey()를 이요해 나중에 생성된 게시물의 번호를 확인할 수 있게 작성하고, 이에 대한 테스트 코드는 아래와 같이 작성한다.
< BoardServiceTests 클래스 >
@Test
public void testRegister() {
BoardVO board = new BoardVO();
board.setTitle("새로 작성하는 글");
board.setContent("새로 작성하는 내용");
board.setWriter("newbie");
service.register(board);
log.info("생성된 게시물의 번호: " + board.getBno());
}
- testRegister()의 테스트 결과는 다음과 같이 생성된 게시물의 번호를 확인할 수 있다.
INFO : jdbc.sqltiming - insert into tbl_board (bno,title,content, writer) values (41, '새로 작성하는 글', '새로 작성하는 내용', 'newbie')
{executed in 70 msec}
INFO : jdbc.audit - 1. PreparedStatement.execute() returned false
INFO : jdbc.audit - 1. PreparedStatement.getUpdateCount() returned 1
INFO : jdbc.audit - 1. PreparedStatement.isClosed() returned false
INFO : jdbc.audit - 1. PreparedStatement.close() returned
INFO : jdbc.audit - 1. Connection.clearWarnings() returned
INFO : org.zerock.service.BoardServiceTests - 생성된 게시물의 번호: 41
9.2.2 목록(리스트) 작업의 구현과 테스트
- BoardServiceImpl 클래스에서 현재 테이블에 저장된 모든 데이터를 가져오는 getList()는 아래와 같이 구현된다.
< BoardServiceImpl 클래스 >
@Override
public List<BoardVO> getList() {
log.info("getList.......");
return mapper.getList();
}
< org.zerock.service.BoardServiceTest 클래스 >
// 테이블에 저장된 모든 데이터를 가져오기
@Test
public void testGetList() {
service.getList().forEach(board -> log.info(board));
}
- 테스트의 실행 결과로 등록 작업을 테스트 할 때 추가된 데이터가 정상적으로 나오는지 확인한다.
INFO : jdbc.resultsettable -
|----|---------------------|----------------------|-------|----------------------|----------------------|
|bno |title |content |writer |regdate |updatedate |
|----|---------------------|----------------------|-------|----------------------|----------------------|
|1 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:55.0 |2023-08-09 11:33:55.0 |
|2 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:56.0 |2023-08-09 11:33:56.0 |
|4 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:57.0 |2023-08-09 11:33:57.0 |
|5 |수정된 제목 |수정된 제목 |user00 |2023-08-09 11:34:00.0 |2023-08-09 20:31:20.0 |
|21 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 19:31:42.0 |2023-08-09 19:31:42.0 |
|22 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 19:36:11.0 |2023-08-09 19:36:11.0 |
|23 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 19:36:11.0 |2023-08-09 19:36:11.0 |
|24 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:11:11.0 |2023-08-09 20:11:11.0 |
|25 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:11:11.0 |2023-08-09 20:11:11.0 |
|26 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:20:00.0 |2023-08-09 20:20:00.0 |
|27 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:20:00.0 |2023-08-09 20:20:00.0 |
|28 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:31:20.0 |2023-08-09 20:31:20.0 |
|29 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:31:20.0 |2023-08-09 20:31:20.0 |
|41 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 22:55:55.0 |2023-08-09 22:55:55.0 |
|----|---------------------|----------------------|-------|----------------------|----------------------|
9.2.3 조회 작업의 구현과 테스트
- 조회는 게시물의 번호가 파라미터이고 BoardVO의 인스턴스가 리턴이 된다.
< BoardServiceImpl 클래스 >
// 게시물 조회
@Override
public BoardVO get(Long bno) {
log.info("get......" + bno);
return mapper.read(bno);
}
< org.zerock.service.BoardServiceTests 클래스 >
// 게시물 조회
@Test
public void testGet() {
log.info(service.get(1L));
}
INFO : jdbc.resultsettable -
|----|---------------------|----------------------|-------|----------------------|----------------------|
|bno |title |content |writer |regdate |updatedate |
|----|---------------------|----------------------|-------|----------------------|----------------------|
|1 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:55.0 |2023-08-09 11:33:55.0 |
|2 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:56.0 |2023-08-09 11:33:56.0 |
|4 |테스트 제목 |테스트 내용 |USER00 |2023-08-09 11:33:57.0 |2023-08-09 11:33:57.0 |
|5 |수정된 제목 |수정된 제목 |user00 |2023-08-09 11:34:00.0 |2023-08-09 20:31:20.0 |
|21 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 19:31:42.0 |2023-08-09 19:31:42.0 |
|22 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 19:36:11.0 |2023-08-09 19:36:11.0 |
|23 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 19:36:11.0 |2023-08-09 19:36:11.0 |
|24 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:11:11.0 |2023-08-09 20:11:11.0 |
|25 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:11:11.0 |2023-08-09 20:11:11.0 |
|26 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:20:00.0 |2023-08-09 20:20:00.0 |
|27 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:20:00.0 |2023-08-09 20:20:00.0 |
|28 |새로 작성하는 글 select key |새로 작성하는 내용 select key |newbie |2023-08-09 20:31:20.0 |2023-08-09 20:31:20.0 |
|29 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 20:31:20.0 |2023-08-09 20:31:20.0 |
|41 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 22:55:55.0 |2023-08-09 22:55:55.0 |
|42 |새로 작성하는 글 |새로 작성하는 내용 |newbie |2023-08-09 23:03:06.0 |2023-08-09 23:03:06.0 |
|----|---------------------|----------------------|-------|----------------------|----------------------|
9.2.4 삭제/수정 구현과 테스트
- 삭제/수정은 메서드의 리턴 타입을 void로 설계할 수 있지만 엄격하게 처리하기 위해 Boolean 타입으로 처리한다.
< org.zerock.service.BoardServiceImpl 클래스 >
// 게시물 수정
@Override
public boolean modify(BoardVO board) {
log.info("modify......." + board);
return mapper.update(board) == 1;
}
// 게시물 삭제
@Override
public boolean remove(Long bno) {
log.info("remove......" + bno);
return mapper.delete(bno) == 1;
}
- 정상적으로 수정과 삭제가 이루어지면 1이라는 값이 반환되기 때문에 '==' 연산자를 이용해서 true/false를 처리할 수 있다.
- 테스트 코드는 다음과 같이 작성한다.
< org.zerock.service.BoardServiceTests 클래스 >
// 게시물 삭제
@Test
public void testDelete() {
// 게시물 번호의 존재 여부를 확인하고 테스트 할 것
log.info("REMOVE RESULT: " + service.remove(2L));
}
// 게시물 수정
@Test
public void testUpdate() {
BoardVO board = service.get(1L);
if (board == null) {
return;
}
board.setTitle("제목 수정합니다.");
log.info("MODIFY RESULT: " + service.modify(board));
}
- testDelete()의 경우에는 해당 게시물이 존재할 때 true를 반환하는 것을 확인할 수 있고, testUpdate()의 경우에는 특정한 게시물을 먼저 조회하고, title 값을 수정한 후 이를 업데이트한다.