From 961a02eed8ab0d7f2125351a2a00b6cdb538a38d Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 01:40:23 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jacoco/api/controller/TestControllerTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/demo/jacoco/api/controller/TestControllerTest.java b/src/test/java/demo/jacoco/api/controller/TestControllerTest.java index 10f2571..fb388fc 100644 --- a/src/test/java/demo/jacoco/api/controller/TestControllerTest.java +++ b/src/test/java/demo/jacoco/api/controller/TestControllerTest.java @@ -35,4 +35,17 @@ void test() throws Exception { .andExpect(status().isOk()) .andExpect(content().string("Test")); } + + @DisplayName("테스트 컨트롤러에서 Example 문자열을 반환한다.") + @Test + void example() throws Exception { + // Given + given(testService.getExample()) + .willReturn("Example"); + + // When & Then + mockMvc.perform(get("/example")) + .andExpect(status().isOk()) + .andExpect(content().string("Example")); + } } \ No newline at end of file From dbd588bb2035f975ae3fb79c248f9f79658f0835 Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 02:02:36 +0900 Subject: [PATCH 2/6] =?UTF-8?q?workflow=20=EA=B6=8C=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EC=97=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 1 - src/main/resources/application.yaml | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yaml diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 3cc6d12..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=jacoco diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..6580f14 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: jacoco-test \ No newline at end of file From 123684485db4841e7d7c52151603f896be2b3d64 Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 02:02:50 +0900 Subject: [PATCH 3/6] =?UTF-8?q?jacoco=20Report=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/jacoco-report.yml | 5 +++-- build.gradle | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/jacoco-report.yml b/.github/workflows/jacoco-report.yml index 09562d2..3be3152 100644 --- a/.github/workflows/jacoco-report.yml +++ b/.github/workflows/jacoco-report.yml @@ -5,7 +5,7 @@ on: branches: [ "main" ] jobs: - build: + jacoco-report: runs-on: ubuntu-latest permissions: contents: read @@ -28,7 +28,8 @@ jobs: uses: Madrapps/jacoco-report@v1.7.1 with: title: Test Coverage Report - paths: ${{ github.workspace }}/build/jacocoReport/test/jacocoTestReport.xml + id: jacocoReport + paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml token: ${{ secrets.GITHUB_TOKEN }} min-coverage-overall: 50 min-coverage-changed-files: 50 diff --git a/build.gradle b/build.gradle index 0a2991f..25afc55 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,6 @@ java { jacoco { toolVersion = "0.8.11" - reportsDirectory = layout.buildDirectory.dir('jacocoReport') } configurations { From dfc2e4bb9fe8cdc41f4c028fb329a004f3130818 Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 02:31:37 +0900 Subject: [PATCH 4/6] =?UTF-8?q?Workflow=20=EA=B6=8C=ED=95=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/jacoco-report.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/jacoco-report.yml b/.github/workflows/jacoco-report.yml index 3be3152..8ebedad 100644 --- a/.github/workflows/jacoco-report.yml +++ b/.github/workflows/jacoco-report.yml @@ -9,6 +9,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + pull-requests: write steps: - uses: actions/checkout@v4 From d855ea6078af67d8cbf4a062b63ba0cfa3a4d5dc Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 02:49:21 +0900 Subject: [PATCH 5/6] =?UTF-8?q?JPA=20=EB=B0=8F=20H2=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 11 +++++++++-- src/main/resources/application.yaml | 11 ++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 25afc55..181b86c 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,18 @@ repositories { } dependencies { + // spring boot implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // lombok + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + // h2 + runtimeOnly 'com.h2database:h2' } tasks.named('test') { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 6580f14..282c3f7 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,3 +1,12 @@ spring: application: - name: jacoco-test \ No newline at end of file + name: jacoco-test + + datasource: + url: jdbc:h2:mem:testdb + username: sa + password: password + driver-class-name: org.h2.Driver + jpa: + hibernate: + ddl-auto: create \ No newline at end of file From 7e32c2796ecc5e150faa1e7bb5878933b0c8e82f Mon Sep 17 00:00:00 2001 From: sangjun Date: Thu, 31 Oct 2024 04:26:01 +0900 Subject: [PATCH 6/6] =?UTF-8?q?Post=20=EA=B4=80=EB=A0=A8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++- .../jacoco/api/controller/PostController.java | 32 ++++++++++++++ .../java/demo/jacoco/api/dto/ListWrapper.java | 8 ++++ .../jacoco/api/dto/PostCreateRequest.java | 17 +++++++ .../demo/jacoco/api/dto/PostInfoResponse.java | 21 +++++++++ .../demo/jacoco/api/service/PostService.java | 26 +++++++++++ .../entity/post/PostJpaEntity.java | 39 ++++++++++++++++ .../repository/PostJpaRepository.java | 7 +++ .../repository/PostRepository.java | 9 ++++ .../repository/PostRepositoryImpl.java | 25 +++++++++++ .../repository/PostRepositoryTest.java | 44 +++++++++++++++++++ 11 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 src/main/java/demo/jacoco/api/controller/PostController.java create mode 100644 src/main/java/demo/jacoco/api/dto/ListWrapper.java create mode 100644 src/main/java/demo/jacoco/api/dto/PostCreateRequest.java create mode 100644 src/main/java/demo/jacoco/api/dto/PostInfoResponse.java create mode 100644 src/main/java/demo/jacoco/api/service/PostService.java create mode 100644 src/main/java/demo/jacoco/persistence/entity/post/PostJpaEntity.java create mode 100644 src/main/java/demo/jacoco/persistence/repository/PostJpaRepository.java create mode 100644 src/main/java/demo/jacoco/persistence/repository/PostRepository.java create mode 100644 src/main/java/demo/jacoco/persistence/repository/PostRepositoryImpl.java create mode 100644 src/test/java/demo/jacoco/persistence/repository/PostRepositoryTest.java diff --git a/build.gradle b/build.gradle index 181b86c..c76bd8d 100644 --- a/build.gradle +++ b/build.gradle @@ -59,8 +59,9 @@ jacocoTestReport { classDirectories.setFrom( files(classDirectories.files.collect { fileTree(dir: it, excludes: [ - '**/domain/**', - '**/global/**', + '**/*dto*', + '**/*entity*', + '**/*Jpa*', '**/*Application*' ]) }) diff --git a/src/main/java/demo/jacoco/api/controller/PostController.java b/src/main/java/demo/jacoco/api/controller/PostController.java new file mode 100644 index 0000000..2260295 --- /dev/null +++ b/src/main/java/demo/jacoco/api/controller/PostController.java @@ -0,0 +1,32 @@ +package demo.jacoco.api.controller; + +import demo.jacoco.api.dto.PostCreateRequest; +import demo.jacoco.api.dto.PostInfoResponse; +import demo.jacoco.api.service.PostService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/posts") +public class PostController { + + private final PostService postService; + + public PostController(PostService postService) { + this.postService = postService; + } + + @PostMapping + public void createPost(@RequestBody PostCreateRequest request) { + postService.createPost(request); + } + + @GetMapping("/{id}") + public PostInfoResponse getPost(@PathVariable Long id){ + return postService.getPost(id); + } +} diff --git a/src/main/java/demo/jacoco/api/dto/ListWrapper.java b/src/main/java/demo/jacoco/api/dto/ListWrapper.java new file mode 100644 index 0000000..7d9f9ea --- /dev/null +++ b/src/main/java/demo/jacoco/api/dto/ListWrapper.java @@ -0,0 +1,8 @@ +package demo.jacoco.api.dto; + +import java.util.List; + +public record ListWrapper( + List result +) { +} diff --git a/src/main/java/demo/jacoco/api/dto/PostCreateRequest.java b/src/main/java/demo/jacoco/api/dto/PostCreateRequest.java new file mode 100644 index 0000000..41ec0f9 --- /dev/null +++ b/src/main/java/demo/jacoco/api/dto/PostCreateRequest.java @@ -0,0 +1,17 @@ +package demo.jacoco.api.dto; + +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import lombok.Builder; + +@Builder +public record PostCreateRequest( + String title, + String content +) { + public PostJpaEntity toEntity() { + return PostJpaEntity.builder() + .title(title) + .content(content) + .build(); + } +} diff --git a/src/main/java/demo/jacoco/api/dto/PostInfoResponse.java b/src/main/java/demo/jacoco/api/dto/PostInfoResponse.java new file mode 100644 index 0000000..17ce839 --- /dev/null +++ b/src/main/java/demo/jacoco/api/dto/PostInfoResponse.java @@ -0,0 +1,21 @@ +package demo.jacoco.api.dto; + +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import lombok.Builder; + +@Builder +public record PostInfoResponse( + Long id, + String title, + String content, + Integer likeCount +) { + public static PostInfoResponse fromEntity(PostJpaEntity postJpaEntity) { + return PostInfoResponse.builder() + .id(postJpaEntity.getId()) + .title(postJpaEntity.getTitle()) + .content(postJpaEntity.getContent()) + .likeCount(postJpaEntity.getLikeCount()) + .build(); + } +} diff --git a/src/main/java/demo/jacoco/api/service/PostService.java b/src/main/java/demo/jacoco/api/service/PostService.java new file mode 100644 index 0000000..7c916b8 --- /dev/null +++ b/src/main/java/demo/jacoco/api/service/PostService.java @@ -0,0 +1,26 @@ +package demo.jacoco.api.service; + +import demo.jacoco.api.dto.PostCreateRequest; +import demo.jacoco.api.dto.PostInfoResponse; +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import demo.jacoco.persistence.repository.PostRepository; +import org.springframework.stereotype.Service; + +@Service +public class PostService { + + private final PostRepository postRepository; + + public PostService(final PostRepository postRepository) { + this.postRepository = postRepository; + } + + public void createPost(PostCreateRequest request) { + postRepository.save(request.toEntity()); + } + + public PostInfoResponse getPost(Long id){ + PostJpaEntity postJpaEntity = postRepository.getById(id); + return PostInfoResponse.fromEntity(postJpaEntity); + } +} diff --git a/src/main/java/demo/jacoco/persistence/entity/post/PostJpaEntity.java b/src/main/java/demo/jacoco/persistence/entity/post/PostJpaEntity.java new file mode 100644 index 0000000..a7e593f --- /dev/null +++ b/src/main/java/demo/jacoco/persistence/entity/post/PostJpaEntity.java @@ -0,0 +1,39 @@ +package demo.jacoco.persistence.entity.post; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Table(name = "post") +@Entity +public class PostJpaEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "post_id") + private Long id; + + @Column(name = "post_title", nullable = false) + private String title; + + @Column(name = "post_content") + private String content; + + @Column(name = "post_like_count") + private Integer likeCount; + + protected PostJpaEntity() {} + + @Builder + private PostJpaEntity(String title, String content) { + this.title = title; + this.content = content; + this.likeCount = 0; + } +} diff --git a/src/main/java/demo/jacoco/persistence/repository/PostJpaRepository.java b/src/main/java/demo/jacoco/persistence/repository/PostJpaRepository.java new file mode 100644 index 0000000..e311170 --- /dev/null +++ b/src/main/java/demo/jacoco/persistence/repository/PostJpaRepository.java @@ -0,0 +1,7 @@ +package demo.jacoco.persistence.repository; + +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostJpaRepository extends JpaRepository { +} diff --git a/src/main/java/demo/jacoco/persistence/repository/PostRepository.java b/src/main/java/demo/jacoco/persistence/repository/PostRepository.java new file mode 100644 index 0000000..d914034 --- /dev/null +++ b/src/main/java/demo/jacoco/persistence/repository/PostRepository.java @@ -0,0 +1,9 @@ +package demo.jacoco.persistence.repository; + +import demo.jacoco.persistence.entity.post.PostJpaEntity; + +public interface PostRepository { + void save(PostJpaEntity postJpaEntity); + + PostJpaEntity getById(Long id); +} diff --git a/src/main/java/demo/jacoco/persistence/repository/PostRepositoryImpl.java b/src/main/java/demo/jacoco/persistence/repository/PostRepositoryImpl.java new file mode 100644 index 0000000..a28773a --- /dev/null +++ b/src/main/java/demo/jacoco/persistence/repository/PostRepositoryImpl.java @@ -0,0 +1,25 @@ +package demo.jacoco.persistence.repository; + +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import org.springframework.stereotype.Repository; + +@Repository +public class PostRepositoryImpl implements PostRepository{ + + private final PostJpaRepository postJpaRepository; + + public PostRepositoryImpl(PostJpaRepository postJpaRepository) { + this.postJpaRepository = postJpaRepository; + } + + @Override + public void save(PostJpaEntity postJpaEntity) { + postJpaRepository.save(postJpaEntity); + } + + @Override + public PostJpaEntity getById(Long id) { + return postJpaRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("Post not found")); + } +} \ No newline at end of file diff --git a/src/test/java/demo/jacoco/persistence/repository/PostRepositoryTest.java b/src/test/java/demo/jacoco/persistence/repository/PostRepositoryTest.java new file mode 100644 index 0000000..f116d13 --- /dev/null +++ b/src/test/java/demo/jacoco/persistence/repository/PostRepositoryTest.java @@ -0,0 +1,44 @@ +package demo.jacoco.persistence.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import demo.jacoco.api.dto.PostCreateRequest; +import demo.jacoco.persistence.entity.post.PostJpaEntity; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; + +@DataJpaTest +@Import(PostRepositoryImpl.class) +class PostRepositoryTest { + + @Autowired + private PostRepository postRepository; + + @DisplayName("포스트를 저장할 수 있다.") + @Test + void save() { + // Given + PostCreateRequest postCreateRequest = createPostRequest("테스트 제목", "테스트 내용"); + + // When + postRepository.save(postCreateRequest.toEntity()); + + // Then + PostJpaEntity postJpaEntity = postRepository.getById(1L); + assertThat(postJpaEntity).isNotNull() + .extracting("title", "content") + .containsExactly("테스트 제목", "테스트 내용"); + } + + private static PostCreateRequest createPostRequest(String title, String content) { + return PostCreateRequest.builder() + .title(title) + .content(content) + .build(); + } + +} \ No newline at end of file