API

#1 TEST CODE 작성 : Todo API 만들기

letsDoDev 2024. 12. 14. 23:35

※ 테스트 코드 작성 이전, 테스트 코드 작성에 필요한 Todo API 작성해서 기록한 게시물

  테스트 코드는 다음 게시물에 작성 예정

[프로젝트 생성]

- 스프링 이니셜라이저 사용

spring-boot : 3.4.0 ver

java(jdk) : 21

 

(lombok 추가하지 않았고 소스로 직접 작성하여 사용)

 

Dependency 추가

 

 

[패키지 구조]

[프로젝트 소스 및 환경 설정]

- build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.4.0'
	id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.testcode'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(21)
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	runtimeOnly 'com.h2database:h2'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

- application.yml

spring:
  application:
    name: jpah2

  datasource:
    url: jdbc:h2:tcp://localhost/~/test  # In-memory H2 DB
    driver-class-name: org.h2.Driver
    username: sa  # root
    password:  # inital pw is not exist
    hikari:
      pool-name: HikariCP  # HikariCP
  h2:
    console:
      enabled: true  # H2 log use : true
      path: /h2-console  #
  jpa:
    hibernate:
      ddl-auto: create  # JPA DDL option :   create, update... etc
    show-sql: true  # show sql query : true
    database-platform: org.hibernate.dialect.H2Dialect  # H2 DB Hibernate Dialect : jpa dialect target is h2 db

 

- TodoController

package com.testcode.jpah2.todo.controller;

import com.testcode.jpah2.todo.dto.RequestTodoDto;
import com.testcode.jpah2.todo.dto.ResponseTodoDto;
import com.testcode.jpah2.todo.service.TodoService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/todo/")
public class TodoController {

    private final TodoService todoService;

    public TodoController(TodoService todoService) {
        this.todoService = todoService;
    }

    @GetMapping("/findAll")
    public List<ResponseTodoDto> findAllTodo() {
        return todoService.findAllTodo();
    }

    @GetMapping("/find/{todoId}")
    public ResponseTodoDto findTodo(@PathVariable("todoId") Long todoId) {
        return todoService.findTodoById(todoId);
    }

    @PostMapping("/insert")
    public void insertTodo(@RequestBody RequestTodoDto requestTodoDto) {
        todoService.insertTodo(requestTodoDto);
    }

    @PostMapping("/update")
    public ResponseTodoDto updateTodo(@RequestBody RequestTodoDto requestTodoDto) {
        return todoService.updateTodo(requestTodoDto);
    }

    @PatchMapping("/remove/{todoId}")
    public void removeTood(@PathVariable Long todoId) {
        todoService.removeTodoById(todoId);
    }
}

 

- Todo

package com.testcode.jpah2.todo.domain;

import com.testcode.jpah2.todo.dto.RequestTodoDto;
import com.testcode.jpah2.todo.dto.ResponseTodoDto;
import jakarta.persistence.*;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Entity
@DynamicInsert
public class Todo {

    @Id
    // @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // @Column(name = "TITLE")
    private String title;

    // @Column(name = "DATE")
    @CurrentTimestamp
    // @UpdateTimestamp
    private LocalDateTime date;

    // @Column(name = "IS_FINISH")
    @Column(columnDefinition = "BOOLEAN DEFAULT FALSE")
    private Boolean isFinish;

    protected Todo() {
    }

    public Todo(Long id, String title, LocalDateTime date, Boolean isFinish) {
        this.id = id;
        this.title = title;
        this.date = date;
        this.isFinish = isFinish;
    }

    public Long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public Boolean getIsFinish() {
        return isFinish;
    }


    // builder 직접 생성 -------------------------------------
    // 빌더 클래스
    public static class Builder {
        private Long id;
        private String title;
        private LocalDateTime date;
        private Boolean isFinish;

        // Builder 메서드들
        public Builder id(Long id) {
            this.id = id;
            return this;
        }

        public Builder title(String title) {
            this.title = title;
            return this;
        }

        public Builder date(LocalDateTime date) {
            this.date = date;
            return this;
        }

        public Builder isFinish(Boolean isFinish) {
            this.isFinish = isFinish;
            return this;
        }

        // 빌더 객체를 사용하여 User 객체 생성
        public Todo build() {
            return new Todo(id, title, date, isFinish);
        }
    }

    // 빌더를 반환하는 정적 메서드
    public static Builder builder() {
        return new Builder();
    }
    // ------------------------------------------ builder 직접 생성

    public void updateTodo(RequestTodoDto requestTodoDto) {
        this.id = requestTodoDto.getId();
        this.title = requestTodoDto.getTitle();
        this.date = LocalDateTime.now();
        this.isFinish = false;
    }
}

 

 

- RequestTodoDto

package com.testcode.jpah2.todo.dto;

import java.time.LocalDateTime;

public class RequestTodoDto {
    long id;
    String title;
    LocalDateTime date;
    boolean isFinish;

    public RequestTodoDto() {
    }

    public RequestTodoDto(long id, String title, LocalDateTime date, boolean isFinish) {
        this.id = id;
        this.title = title;
        this.date = date;
        this.isFinish = isFinish;
    }

    public long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public boolean getIsFinish() {
        return isFinish;
    }
}

 

- ResponseTodoDto

package com.testcode.jpah2.todo.dto;

import com.testcode.jpah2.todo.domain.Todo;

import java.time.LocalDateTime;

public class ResponseTodoDto {
    long id;
    String title;
    LocalDateTime date;
    boolean isFinish;

    public ResponseTodoDto() {
    }

    public ResponseTodoDto(long id, String title, LocalDateTime date, boolean isFinish) {
        this.id = id;
        this.title = title;
        this.date = date;
        this.isFinish = isFinish;
    }

    public long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public boolean getIsFinish() { return isFinish; }

    public ResponseTodoDto(Todo todo) {
        this.id = todo.getId();
        this.title = todo.getTitle();
        this.date = todo.getDate();
        this.isFinish = todo.getIsFinish();
    }
}

 

- TodoRespository

package com.testcode.jpah2.todo.repository;

import com.testcode.jpah2.todo.domain.Todo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.List;
import java.util.Optional;

@Repository
public interface TodoRepository extends JpaRepository<Todo,Long> {
    // id로 todo 삭제
    void deleteById(Long id);
}

 

- TodoService

package com.testcode.jpah2.todo.service;

import com.testcode.jpah2.todo.domain.Todo;
import com.testcode.jpah2.todo.dto.RequestTodoDto;
import com.testcode.jpah2.todo.dto.ResponseTodoDto;

import java.util.List;

public interface TodoService {
    // 전체 todo 조회
    public List<ResponseTodoDto> findAllTodo();
    
    // id로 특정 todo 조회
    public ResponseTodoDto findTodoById(Long id);
    
    // todo 등록
    public void insertTodo(RequestTodoDto todo);
    
    // todo 수정
    public ResponseTodoDto updateTodo(RequestTodoDto requestTodoDto);
    
    // todo 삭제
    public void removeTodoById(Long id);
}

 

 

- TodoServiceImpl

package com.testcode.jpah2.todo.service;

import com.testcode.jpah2.todo.domain.Todo;
import com.testcode.jpah2.todo.dto.RequestTodoDto;
import com.testcode.jpah2.todo.dto.ResponseTodoDto;
import com.testcode.jpah2.todo.repository.TodoRepository;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Transactional
@Service
public class TodoServiceImpl implements TodoService{

    private final TodoRepository todoRepository;

    public TodoServiceImpl(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @Override
    public List<ResponseTodoDto> findAllTodo() {
        List<ResponseTodoDto> findTodos = todoRepository.findAll().stream().map(todo -> new ResponseTodoDto(
                todo.getId(),
                todo.getTitle(),
                todo.getDate(),
                todo.getIsFinish()
            )).collect(Collectors.toList());

        return findTodos;
    }

    @Override
    public ResponseTodoDto findTodoById(Long id) {
        return todoRepository.findById(id).map(todo -> new ResponseTodoDto(
                todo.getId(),
                todo.getTitle(),
                todo.getDate(),
                todo.getIsFinish()
        )).orElse(new ResponseTodoDto());
    }

    @Override
    public void insertTodo(RequestTodoDto requestTodoDto) {
        todoRepository.save(Todo
                .builder()
                .title(requestTodoDto.getTitle())
                .build());
    }

    @Override
    public ResponseTodoDto updateTodo(RequestTodoDto requestTodoDto) {
        Optional<Todo> findTodo = todoRepository.findById(requestTodoDto.getId());

        if (!findTodo.isPresent()) {
            return new ResponseTodoDto();
        } else {
            findTodo.get().updateTodo(requestTodoDto);
            return new ResponseTodoDto(findTodo.get());
        }
    }

    @Override
    public void removeTodoById(Long id) {
        Optional<Todo> findTodo = todoRepository.findById(id);
        if (findTodo.isPresent()) {
            todoRepository.deleteById(id);
        }
    }


}

[실행 결과]