본문 바로가기
Dev/Spring

스프링 5 @Service 서비스 구현과 테스트

by vellahw 2022. 10. 31.

 

 

0. BoardMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="org.hw.mapper.BoardMapper">
    
    <select id="getList" resultType="org.hw.domain.BoardVO">
    <![CDATA[
        select * from tbl_board where bno > 0
    ]]>
    </select>
 
    <insert id="insert">
        insert into tbl_board (bno, title, content, writer)
        values (seq_board.NEXTVAL, #{title}, #{content}, #{writer})
    </insert>
    
    <insert id="insertSelectKey">
        <selectKey keyProperty="bno" order="BEFORE" resultType="long">
            select seq_board.NEXTVAL from dual
        </selectKey>
 
        insert into tbl_board (bno, title, content, writer)
        values (#{bno}, #{title}, #{content}, #{writer})
    </insert>
    
    <select id="read" resultType="org.hw.domain.BoardVO" >
        select * from tbl_board where bno = #{bno}
    </select>
    
    <delete id="delete">
        delete from tbl_board where bno = #{bno}
    </delete>
    
    <update id="update">
        update tbl_board set
        title=#{title}, content=#{content}, writer=#{writer}, updateDate=sysdate
        where bno = #{bno}
    </update>
 
</mapper> 
cs

 

 

1. BoardService 인터페이스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package org.hw.service;
 
import java.util.List;
 
import org.hw.domain.BoardVO;
 
public interface BoardService {
    
    public void register(BoardVO board);
    
    public BoardVO get(Long bno);
    
    public boolean modify(BoardVO board);
 
    public boolean remove(Long bno);
    
    public List<BoardVO> getList();
}
cs

 

 

2. BoardService를 구현한 구현체 BoardServiceImpl

(클래스 일부임)

 

💡 @Service 어노테이션 : 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용함.

BoardServiceImpl가 정상적으로 작동하기 위해선 BoardMapper 객체가 필요하다.

스프링 4.3부터는 단일 파라미터를 받는 생성자의 경우에 필요한 파라미터를 자동으로 주입할 수 있다.

@AllArgsContstructor는 모든 파라미터를 이용하는 생성자를 만든다.

 

아웃라인을 확인 해보면 BoardMapper를 주입 받는 생성자가 만들어진 것을 확인 할 수 있음

 

* BoardMapper 인터페이스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.hw.mapper;
 
import java.util.List;
 
import org.apache.ibatis.annotations.Select;
import org.hw.domain.BoardVO;
 
public interface BoardMapper {
    
//    @Select("select * from tbl_board where bno > 0")
    public List<BoardVO> getList();
    
    public void insert(BoardVO borad);
    
    public void insertSelectKey(BoardVO board);
    
    public BoardVO read(Long bno);
    
    public int delete(Long bno);
 
    public int update(BoardVO borad);
}
cs

 

* BoardVO 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package org.hw.domain;
 
import java.sql.Date;
 
import lombok.Data;
 
@Data
public class BoardVO {
    
    private Long bno;
    private String title;
    private String content;
    private String writer;
    private Date regdate;
    private Date updateDate;
}    
cs

 

 

3. root-context.xml에 설정 추가

비즈니스 계층의 인터페이스와 구현 클래스가 작성 되었다면 이를 스프링의 빈으로 인식하기 위해 root-context.xml에 @Service 어노테이션이 있는 패키지를 스캔 하도록 추가해야 한다.

 

네임스페이스 탭에서 context 체크 후 아래 코드를 추가한다.

1
2
<!-- Service 클래스 스캔 -->
<context:component-scan    base-package="org.hw.service" />
cs

 

 

4. src/test/java에 테스트 클래스 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.hw.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")
@Log4j
public class BoardServiceTest {
    
    @Setter(onMethod_ = { @Autowired })
    private BoardService servie;
    
    //BoardService 객체가 제대로 주입 가능한지 확인하는 테스트
    @Test
    public void testExist() {
        log.info(servie);
        assertNotNull(servie);
    }
}
 
cs

첫 번째 BoardService 객체가 제대로 주입 가능한지 확인하는 작업이다.

 

JUnit Test로 실행하면 정상 작동 확인!

 


 

🎇 등록 작업의 구현과 테스트

등록 작업은 BoardServiceImpl에서 파라미터로 전달되는 BoardVO 타입의 객체를 BoardMepper를 통해 처리한다.

 

1) BoardServiceImpl 클래스의 register 메소드 수정

mapper의 insertSelectKey()를 이용해서 나중에 생성된 게시물의 번호를 확인할 수 있게 작성함

 

* BoardMapper에 작성된 insertSelectKey()

 

2) BoardServiceTest 클래스에 테스트 코드 작성

 

테스트 결과

 

DB에도 정상적으로 입력된 것을 확인

 

 

 

🎇 목록(리스트) 작업의 구현과 테스트

  • 현재 테이블에 저장된 모든 데이터를 가져오는 getList()의 구현

 

1) BoardServiceImpl 클래스의 getList() 메소드 수정

 

2) BoardServiceTest 클래스에 테스트 코드 작성

 

테스트 실행 결과

위의 등록 작업에서 추가한 데이터를 정상적으로 가져올 수 있음을 확인

 

 

 

🎇 조회 작업의 구현과 테스트

  • 조회는 게시물의 번호가  파라미터이고 BoardVO의 인스턴스가 리턴됨

 

1) BoardServiceImpl 클래스의 get() 메소드 수정

 

*BoardMapper 인터페이스의 read() 추상메소드

 

2) BoardServiceTest 클래스에 테스트 코드 작성

 

select문 동작 확인

 

정상 조회 확인

 

 

 

🎇 삭제/수정 작업의 구현과 테스트

  • 삭제/수정은 메소드의 리턴 타입을 void로 설계할 수도 있지만 엄격하게 처리하기 위해 boolean 타입으로 처리함

 

1) BoardServiceImple 클래스의 modify(), remove() 메소드 수정

정상적으로 수정과 삭제가 이루어지면 1이 반환되기 때문에 '==' 연산자를 이용해서 true/false 처리를 할 수 있다.

 

*mapper(BoardMapper 클래스)의 메소드들

 

 

2) BoardServiceTest 클래스에 테스트 코드 작성

 

* 결과 확인

수정/삭제할 데이터 (글 번호 7)

 

수정된 데이터 확인
로그 true 확인

 

 

 

삭제 로그 확인

 

삭제된 데이터 확인

 

 

🎇 완성된 구현체와 테스트 클래스

● 구현체 (BoardServiceImpl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package org.hw.service;
 
import java.util.List;
 
import org.hw.domain.BoardVO;
import org.hw.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import lombok.AllArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
 
@Log4j
@Service //비즈니스 영역 담당하는 객체임을 표시    
@AllArgsConstructor //모든 파라미터를 이용하는 생성자 만듦
public class BoardServiceImpl implements BoardService {
 
//    @Setter(onMethod_ = @Autowired) : spring 4.3 이상에선 자동 처리됨
    private BoardMapper mapper;
    
    @Override
    public void register(BoardVO board) {
        log.info("register!!!!!! " + board );
        
        mapper.insertSelectKey(board);
    }
 
    @Override
    public BoardVO get(Long bno) {
        
        log.info("get!!!!!!!" + bno);
        
        return mapper.read(bno);
    }
 
    @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;
    }
 
    @Override
    public List<BoardVO> getList() {
        
        log.info("getList!!!!!!");
        
        return mapper.getList();
    }
}
cs

 

● 테스트 클래스 (BoardServiceImpl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package org.hw.service;
 
import static org.junit.Assert.assertNotNull;
 
import org.hw.domain.BoardVO;
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")
@Log4j
public class BoardServiceTest {
    
    @Setter(onMethod_ = { @Autowired })
    private BoardService servie;
    
    //BoardService 객체가 제대로 주입 가능한지 확인하는 테스트
    @Test
    public void testExist() {
        log.info(servie);
        assertNotNull(servie);
    }
    
    //등록 테스트
    @Test
    public void testRegister() {
        BoardVO board = new BoardVO();
        board.setTitle("새로 작성하는 글");
        board.setContent("새로 작성하는 내용");
        board.setWriter("새로운 작성자");
        
        servie.register(board);
        
        log.info("생성된 게시물의 번호: " + board.getBno());
    }
 
    //리스트 가져오기
    @Test
    public void testGetList() {
        servie.getList().forEach(board -> log.info(board));;
    }
 
    //게시글 조회
    @Test
    public void testGet() {
        log.info(servie.get(12L));
    }
 
    //게시글 수정
    @Test
    public void testUpdate() {
        
        BoardVO board = servie.get(7L);
        
        if(board == null) {
            return;
        }
        
        board.setTitle("수정된 제목입니다.");
        board.setContent("수정된 내용입니다.");
        board.setWriter("수정된 작성자입니다.");
        
        log.info("수정 결과: " + servie.modify(board));
    }
    
    //게시글 삭제
    @Test
    public void testDelete() {
        log.info("삭제 결과: " + servie.remove(7L));
    }
}
 
cs

댓글