제목의 글을 설명하기에 앞서 정보전달의 목적도 있지만,
제가 잊지않기 위해서 공부 및 정리하며 쓰는 글이라는 사실을 미리 고지합니다.
혹시라도 오입력된 정보가 있다면, 댓글 남겨주세요!
오늘의 Spring Boot 실습 목표는 "공지사항/게시판 만들어보기!" 입니다.
본 게시글에서 다루는 사항은 공지사항/게시판의 기능을 구현하기 위해 DB(Table)을 생성 및 해당 테이블에 대한 CRUD를 테스트 코드를 작성하는 과정입니다.
공지사항/게시판 구현하기 - DB Table 생성 및 CRUD 테스트
사전 준비
아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.
혹시라도 아래 개념이 잘 기억나지 않으시는 분들은 관련 링크를 참조하시기 바랍니다.
파일 구조
Notice User 테이블을 생성하고 CRUD 기능을 테스트하기 위해서 작업해야 할 파일은 총 3개입니다.
아래 폴더/파일 트리 구조와 호출 흐름도는 Notice User 테이블이 전체 구현이 완료된 후 갖춰질 구조입니다.
작업할 파일에 대한 간략한 설명은 아래를 참고하시면 됩니다.
- NoticeUser
- 목적: Notice User 테이블과 매핑되는 객체 정의 파일
- 경로: src\main\java\...\notice\domain
- NoticeUserRepository
- 목적: NoticeUser에 대한 메소드 정의 파일
- 경로: src\main\java\...\notice\repository
- NoticeUserRepositoryTest
- 목적: Notice User 테이블에 관련된 CRUD를 테스트 코드가 구현된 파일
- 경로: src\test\java\...\notice\domain
테이블 구조
[실습] 스프링부트(Spring Boot)로 공지사항/게시판 구현하기 - DB, API 기획/설계하기 를 참조해주세요.
결과 이미지
소스 코드
NoticeUser
위 '테이블 구조'에 링크된 페이지에서 정의한 바와 같이 각 컬럼의 타입과 길이, 속성을 지정합니다.
package com.logsjejustone.webapiserver.notice.domain;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@Entity
public class NoticeUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer Id;
@Column(length = 6)
@NotNull
private String registerEmployeeNo;
@CreatedDate
@NotNull
private LocalDateTime registerDatetime;
@Column(length = 6)
@NotNull
private String updateEmployeeNo;
@CreatedDate
@NotNull
private LocalDateTime updateDatetime;
@Column(length = 20)
private String category;
@Column(length = 200)
private String title;
@Column(columnDefinition = "TEXT")
private String content;
}
NoticeUserRepository
NoticeUser 테이블에 대한 메소드를 정의하는 부분으로 JpaRepository를 상속받아 기본적인 메소드들은 별도로 정의하지 않고 이용할 수 있습니다.
기본적으로 사용할 수 있는 메소드는 'JpaRepository' 링크를 참조해주세요.
package com.logsjejustone.webapiserver.notice.repository;
import com.logsjejustone.webapiserver.notice.domain.NoticeUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface NoticeUserRepository extends JpaRepository<NoticeUser, Integer> {
}
NoticeUserRepositoryTest
NoticeUserRepository를 이용하여 NoticeUser로 매핑된 테이블 객체에 대해서 기본적인 CRUD를 테스트하는 코드입니다.
자세한 코드는 아래 더보기를 클릭하여 확인해주시고, 상세한 코드는 아래 '테스트' 카테고리에서 코드와 결과를 상세하게 기록하겠습니다
package com.logsjejustone.webapiserver.notice.repository;
import com.logsjejustone.webapiserver.notice.domain.NoticeUser;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class NoticeUserRepositoryTest {
@Autowired
private NoticeUserRepository noticeUserRepository;
@Test
public void createNotice () {
// Check 1
LocalDateTime now = LocalDateTime.now();
String employeeNo = "000000";
NoticeUser noticeUser = new NoticeUser();
noticeUser.setRegisterDatetime(now);
noticeUser.setRegisterEmployeeNo(employeeNo);
noticeUser.setUpdateDatetime(now);
noticeUser.setUpdateEmployeeNo(employeeNo);
noticeUser.setCategory("시스템 점검");
noticeUser.setTitle("2022/11/30 시스템 점검 공지");
noticeUser.setContent("아래와 같은 일정으로 시스템 점검 예정임.");
this.noticeUserRepository.save(noticeUser);
assertEquals(1, this.noticeUserRepository.count());
}
@Test
public void readNotice () throws Exception {
// Check 1
List<NoticeUser> lstNoticeUser = this.noticeUserRepository.findAll();
assertEquals(0, lstNoticeUser.size());
}
@Test
public void updateNotice () throws Exception {
// Check 1
Optional<NoticeUser> optNotice = this.noticeUserRepository.findById(2);
assertTrue(optNotice.isPresent());
// Check 2
NoticeUser noticeUser = optNotice.get();
assertEquals("2022/11/30 시스템 점검 공지", noticeUser.getTitle());
// Check 3
String strAfter = "2022/12/30 시스템 점검 공지";
noticeUser.setTitle(strAfter);
this.noticeUserRepository.save(noticeUser);
assertEquals(strAfter, optNotice.get().getTitle());
}
@Test
public void deleteNotice () throws Exception {
// Check 1
Optional<NoticeUser> optNotice = this.noticeUserRepository.findById(2);
assertTrue(optNotice.isPresent());
// Check 2
NoticeUser noticeUser = optNotice.get();
assertEquals("2022/12/30 시스템 점검 공지", noticeUser.getTitle());
// Check 3
this.noticeUserRepository.delete(noticeUser);
assertEquals(0, this.noticeUserRepository.count());
}
}
테스트
CREATE
결과 #1: 테스트 코드 한 번 수행
- 좌측 이미지: JUnit 자체적으로 assertEquals 메소드를 통해 확인한 테스트 결과 → Success (예상값과 실제값이 일치)
- 우측 이미지: MySQL Workbench에서 생성된 notice_user 테이블과 1개의 데이터가 확인됨
결과 #2: 테스트 코드 두 번 수행 (결과 #1 이후 한 번 더 클릭한 경우)
- 좌측 이미지: JUnit 자체적으로 assertEquals 메소드를 통해 확인한 테스트 결과 → Fail (예상값과 실제값이 불일치)
- 의도적으로 Fail이 발생하도록 코드를 구현하였으며, 셋팅된 예상값은 1, 실제값은 2입니다.
- 우측 이미지: MySQL Workbench에서 notice_user 테이블에 데이터 2개가 확인됨
코드
@Test
public void createNotice () {
// Check 1
LocalDateTime now = LocalDateTime.now();
String employeeNo = "000000";
NoticeUser noticeUser = new NoticeUser();
noticeUser.setRegisterDatetime(now);
noticeUser.setRegisterEmployeeNo(employeeNo);
noticeUser.setUpdateDatetime(now);
noticeUser.setUpdateEmployeeNo(employeeNo);
noticeUser.setCategory("시스템 점검");
noticeUser.setTitle("2022/11/30 시스템 점검 공지");
noticeUser.setContent("아래와 같은 일정으로 시스템 점검 예정임.");
this.noticeUserRepository.save(noticeUser);
assertEquals(1, this.noticeUserRepository.count());
}
Query
해당 스키마/DB 내에는 notice_user 테이블이 없기 때문에 Hibernate 자체적으로 DDL Create 문을 생성하여 테이블을 생성 후, 입력한 데이터를 삽입합니다.
READ
결과
- JUnit 자체적으로 assertEquals 메소드를 통해 확인한 테스트 결과 → Success (예상값과 실제값이 일치)
코드
@Test
public void readNotice () throws Exception {
// Check 1
List<NoticeUser> lstNoticeUser = this.noticeUserRepository.findAll();
assertEquals(2, lstNoticeUser.size());
}
Query
UPDATE
결과
- 좌측 이미지: JUnit 자체적으로 assertEquals 메소드를 통해 확인한 테스트 결과 → Success (예상값과 실제값이 일치)
- 우측 이미지: id가 1번인 항목의 title의 날짜가 '2022/12/30'에서 '2022/11/30'으로 변경되었음
코드
@Test
public void updateNotice () throws Exception {
// Check 1
Optional<NoticeUser> optNotice = this.noticeUserRepository.findById(2);
assertTrue(optNotice.isPresent());
// Check 2
NoticeUser noticeUser = optNotice.get();
assertEquals("2022/11/30 시스템 점검 공지", noticeUser.getTitle());
// Check 3
String strAfter = "2022/12/30 시스템 점검 공지";
noticeUser.setTitle(strAfter);
this.noticeUserRepository.save(noticeUser);
assertEquals(strAfter, optNotice.get().getTitle());
}
Query
DELETE
결과
- 좌측 이미지: JUnit 자체적으로 assertEquals 메소드를 통해 확인한 테스트 결과 → Fail (예상값과 실제값이 불일치)
- 의도적으로 Fail이 발생하도록 코드를 구현하였으며, 셋팅된 예상값은 0, 실제값은 1입니다.
- 우측 이미지: id가 2번인 항목에 대해서 데이터가 삭제되었음
코드
@Test
public void deleteNotice () throws Exception {
// Check 1
Optional<NoticeUser> optNotice = this.noticeUserRepository.findById(2);
assertTrue(optNotice.isPresent());
// Check 2
NoticeUser noticeUser = optNotice.get();
assertEquals("2022/12/30 시스템 점검 공지", noticeUser.getTitle());
// Check 3
this.noticeUserRepository.delete(noticeUser);
assertEquals(0, this.noticeUserRepository.count());
}
Query
댓글