From 419571554d4fe28993a731dcf7e8ac3c60e45421 Mon Sep 17 00:00:00 2001 From: raeperd Date: Tue, 13 Apr 2021 19:48:00 +0900 Subject: [PATCH 1/3] [#1] Implements `POST /users/login` --- lombok.config | 1 + .../application/UserLoginRequestDTO.java | 20 ++++++ .../application/UserResponseDTO.java | 33 ++++++++++ .../application/UserRestController.java | 26 ++++++++ .../github/raeperd/realworld/domain/User.java | 45 +++++++++++++ .../realworld/domain/UserRepository.java | 10 +++ .../application/UserRestControllerTest.java | 65 +++++++++++++++++++ 7 files changed, 200 insertions(+) create mode 100644 src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java create mode 100644 src/main/java/io/github/raeperd/realworld/application/UserResponseDTO.java create mode 100644 src/main/java/io/github/raeperd/realworld/application/UserRestController.java create mode 100644 src/main/java/io/github/raeperd/realworld/domain/User.java create mode 100644 src/main/java/io/github/raeperd/realworld/domain/UserRepository.java create mode 100644 src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java diff --git a/lombok.config b/lombok.config index 6aa51d7..a284c48 100644 --- a/lombok.config +++ b/lombok.config @@ -1,2 +1,3 @@ # This file is generated by the 'io.freefair.lombok' Gradle plugin config.stopBubbling = true +lombok.extern.findbugs.addSuppressFBWarnings = true diff --git a/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java b/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java new file mode 100644 index 0000000..d8d2931 --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java @@ -0,0 +1,20 @@ +package io.github.raeperd.realworld.application; + +import io.github.raeperd.realworld.domain.User; +import lombok.Getter; + +@Getter +public class UserLoginRequestDTO { + + private final String email; + private final String password; + + public UserLoginRequestDTO(String email, String password) { + this.email = email; + this.password = password; + } + + public User toUser() { + return User.fromEmailAndPassword(email, password); + } +} diff --git a/src/main/java/io/github/raeperd/realworld/application/UserResponseDTO.java b/src/main/java/io/github/raeperd/realworld/application/UserResponseDTO.java new file mode 100644 index 0000000..cdd9a53 --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/application/UserResponseDTO.java @@ -0,0 +1,33 @@ +package io.github.raeperd.realworld.application; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.annotation.JsonTypeName; +import io.github.raeperd.realworld.domain.User; +import lombok.Getter; + +@JsonTypeName("user") +@JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.NAME) +@Getter +public class UserResponseDTO { + + private final String email; + private final String token; + private final String username; + private final String bio; + private final String image; + + public static UserResponseDTO fromUser(User user) { + return new UserResponseDTO(user); + } + + private UserResponseDTO(User user) { + this.email = user.getEmail(); + this.username = user.getUsername(); + this.bio = user.getBio(); + this.image = user.getImage(); + // TODO: Generate token from user somewhere else + this.token = ""; + } +} diff --git a/src/main/java/io/github/raeperd/realworld/application/UserRestController.java b/src/main/java/io/github/raeperd/realworld/application/UserRestController.java new file mode 100644 index 0000000..3dc08a4 --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/application/UserRestController.java @@ -0,0 +1,26 @@ +package io.github.raeperd.realworld.application; + +import io.github.raeperd.realworld.domain.UserRepository; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import static org.springframework.http.ResponseEntity.of; + +@RestController +public class UserRestController { + + private final UserRepository userRepository; + + public UserRestController(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @PostMapping("/users/login") + public ResponseEntity login(@RequestBody UserLoginRequestDTO loginRequest) { + return of(userRepository.findFirstByEmailAndPassword(loginRequest.getEmail(), loginRequest.getPassword()) + .map(UserResponseDTO::fromUser)); + } + +} diff --git a/src/main/java/io/github/raeperd/realworld/domain/User.java b/src/main/java/io/github/raeperd/realworld/domain/User.java new file mode 100644 index 0000000..71d535e --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/domain/User.java @@ -0,0 +1,45 @@ +package io.github.raeperd.realworld.domain; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class User { + + @Id + private long id; + + private String email; + private String password; + private String username; + private String bio; + private String image; + + protected User() { + } + + public static User fromEmailAndPassword(String email, String password) { + return new User(email, password); + } + + private User(String email, String password) { + this.email = email; + this.password = password; + } + + public String getEmail() { + return email; + } + + public String getUsername() { + return username; + } + + public String getBio() { + return bio; + } + + public String getImage() { + return image; + } +} diff --git a/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java b/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java new file mode 100644 index 0000000..94660c5 --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java @@ -0,0 +1,10 @@ +package io.github.raeperd.realworld.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + + Optional findFirstByEmailAndPassword(String email, String password); +} diff --git a/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java b/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java new file mode 100644 index 0000000..c6eef71 --- /dev/null +++ b/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java @@ -0,0 +1,65 @@ +package io.github.raeperd.realworld.application; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.github.raeperd.realworld.domain.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import static io.github.raeperd.realworld.domain.User.fromEmailAndPassword; +import static java.util.Optional.of; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@AutoConfigureMockMvc +@WebMvcTest(UserRestController.class) +class UserRestControllerTest { + + @MockBean + private UserRepository userRepository; + + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + + @Test + void when_post_login_expect_userRepository_findFirstByEmailAndPassword_called() throws Exception { + final var loginDTO = new UserLoginRequestDTO("email", "password"); + when(userRepository.findFirstByEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword())) + .thenReturn(of(fromEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword()))); + + mockMvc.perform(post("/users/login") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(loginDTO))); + + then(userRepository).should(times(1)) + .findFirstByEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword()); + } + + @Test + void when_post_login_expect_valid_response_body() throws Exception { + when(userRepository.findFirstByEmailAndPassword(anyString(), anyString())) + .thenReturn(of(fromEmailAndPassword("email", "password"))); + + mockMvc.perform(post("/users/login") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new UserLoginRequestDTO("email", "password")))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.user").exists()) + .andExpect(jsonPath("$.user.email").exists()) + .andExpect(jsonPath("$.user.bio").hasJsonPath()) + .andExpect(jsonPath("$.user.image").hasJsonPath()) + .andExpect(jsonPath("$.user.token").hasJsonPath()); + } + +} \ No newline at end of file From 10ae538d2fbb89e36c461f8fe78b87de5995abf4 Mon Sep 17 00:00:00 2001 From: raeperd Date: Wed, 14 Apr 2021 20:40:16 +0900 Subject: [PATCH 2/3] [#1] Implements `POST /users` --- lombok.config | 1 + .../application/UserLoginRequestDTO.java | 4 -- .../application/UserPostRequestDTO.java | 23 ++++++++ .../application/UserRestController.java | 25 +++++---- .../github/raeperd/realworld/domain/User.java | 13 ++--- .../realworld/domain/UserRepository.java | 7 ++- .../raeperd/realworld/domain/UserService.java | 27 ++++++++++ .../application/UserRestControllerTest.java | 53 +++++++++++++++---- .../realworld/domain/UserServiceTest.java | 43 +++++++++++++++ .../raeperd/realworld/domain/UserTest.java | 20 +++++++ 10 files changed, 185 insertions(+), 31 deletions(-) create mode 100644 src/main/java/io/github/raeperd/realworld/application/UserPostRequestDTO.java create mode 100644 src/main/java/io/github/raeperd/realworld/domain/UserService.java create mode 100644 src/test/java/io/github/raeperd/realworld/domain/UserServiceTest.java create mode 100644 src/test/java/io/github/raeperd/realworld/domain/UserTest.java diff --git a/lombok.config b/lombok.config index a284c48..c049ae8 100644 --- a/lombok.config +++ b/lombok.config @@ -1,3 +1,4 @@ # This file is generated by the 'io.freefair.lombok' Gradle plugin config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true lombok.extern.findbugs.addSuppressFBWarnings = true diff --git a/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java b/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java index d8d2931..d955aed 100644 --- a/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java +++ b/src/main/java/io/github/raeperd/realworld/application/UserLoginRequestDTO.java @@ -1,6 +1,5 @@ package io.github.raeperd.realworld.application; -import io.github.raeperd.realworld.domain.User; import lombok.Getter; @Getter @@ -14,7 +13,4 @@ public UserLoginRequestDTO(String email, String password) { this.password = password; } - public User toUser() { - return User.fromEmailAndPassword(email, password); - } } diff --git a/src/main/java/io/github/raeperd/realworld/application/UserPostRequestDTO.java b/src/main/java/io/github/raeperd/realworld/application/UserPostRequestDTO.java new file mode 100644 index 0000000..bda81cb --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/application/UserPostRequestDTO.java @@ -0,0 +1,23 @@ +package io.github.raeperd.realworld.application; + +import io.github.raeperd.realworld.domain.User; +import lombok.Getter; + +@Getter +public class UserPostRequestDTO { + + private final String username; + private final String email; + private final String password; + + public UserPostRequestDTO(String username, String email, String password) { + this.username = username; + this.email = email; + this.password = password; + } + + public User toUser() { + return User.createNewUser(username, email, password); + } + +} diff --git a/src/main/java/io/github/raeperd/realworld/application/UserRestController.java b/src/main/java/io/github/raeperd/realworld/application/UserRestController.java index 3dc08a4..870a9b2 100644 --- a/src/main/java/io/github/raeperd/realworld/application/UserRestController.java +++ b/src/main/java/io/github/raeperd/realworld/application/UserRestController.java @@ -1,26 +1,33 @@ package io.github.raeperd.realworld.application; -import io.github.raeperd.realworld.domain.UserRepository; +import io.github.raeperd.realworld.domain.UserService; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import static org.springframework.http.HttpStatus.CREATED; import static org.springframework.http.ResponseEntity.of; +@RequestMapping("/users") @RestController public class UserRestController { - private final UserRepository userRepository; + private final UserService userService; - public UserRestController(UserRepository userRepository) { - this.userRepository = userRepository; + public UserRestController(UserService userService) { + this.userService = userService; } - @PostMapping("/users/login") + @PostMapping("/login") public ResponseEntity login(@RequestBody UserLoginRequestDTO loginRequest) { - return of(userRepository.findFirstByEmailAndPassword(loginRequest.getEmail(), loginRequest.getPassword()) + return of(userService.login(loginRequest.getEmail(), loginRequest.getPassword()) .map(UserResponseDTO::fromUser)); } + @ResponseStatus(CREATED) + @PostMapping + public UserResponseDTO postUser(@RequestBody UserPostRequestDTO postRequest) { + return UserResponseDTO.fromUser( + userService.createUser(postRequest.toUser())); + } + } diff --git a/src/main/java/io/github/raeperd/realworld/domain/User.java b/src/main/java/io/github/raeperd/realworld/domain/User.java index 71d535e..fc82006 100644 --- a/src/main/java/io/github/raeperd/realworld/domain/User.java +++ b/src/main/java/io/github/raeperd/realworld/domain/User.java @@ -15,18 +15,19 @@ public class User { private String bio; private String image; - protected User() { - } - - public static User fromEmailAndPassword(String email, String password) { - return new User(email, password); + public static User createNewUser(String username, String email, String password) { + return new User(username, email, password); } - private User(String email, String password) { + private User(String username, String email, String password) { + this.username = username; this.email = email; this.password = password; } + protected User() { + } + public String getEmail() { return email; } diff --git a/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java b/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java index 94660c5..055d753 100644 --- a/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java +++ b/src/main/java/io/github/raeperd/realworld/domain/UserRepository.java @@ -1,10 +1,15 @@ package io.github.raeperd.realworld.domain; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.Optional; -public interface UserRepository extends JpaRepository { +@Repository +interface UserRepository extends JpaRepository { Optional findFirstByEmailAndPassword(String email, String password); + + boolean existsByEmail(String email); + } diff --git a/src/main/java/io/github/raeperd/realworld/domain/UserService.java b/src/main/java/io/github/raeperd/realworld/domain/UserService.java new file mode 100644 index 0000000..9f20954 --- /dev/null +++ b/src/main/java/io/github/raeperd/realworld/domain/UserService.java @@ -0,0 +1,27 @@ +package io.github.raeperd.realworld.domain; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +public class UserService { + + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Transactional(readOnly = true) + public Optional login(String email, String password) { + return userRepository.findFirstByEmailAndPassword(email, password); + } + + @Transactional + public User createUser(User user) { + return userRepository.save(user); + } + +} diff --git a/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java b/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java index c6eef71..038e91f 100644 --- a/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java +++ b/src/test/java/io/github/raeperd/realworld/application/UserRestControllerTest.java @@ -1,7 +1,8 @@ package io.github.raeperd.realworld.application; import com.fasterxml.jackson.databind.ObjectMapper; -import io.github.raeperd.realworld.domain.UserRepository; +import io.github.raeperd.realworld.domain.User; +import io.github.raeperd.realworld.domain.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -9,9 +10,11 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; -import static io.github.raeperd.realworld.domain.User.fromEmailAndPassword; +import static io.github.raeperd.realworld.domain.User.createNewUser; import static java.util.Optional.of; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; @@ -25,7 +28,7 @@ class UserRestControllerTest { @MockBean - private UserRepository userRepository; + private UserService userService; @Autowired private MockMvc mockMvc; @@ -33,23 +36,23 @@ class UserRestControllerTest { private ObjectMapper objectMapper; @Test - void when_post_login_expect_userRepository_findFirstByEmailAndPassword_called() throws Exception { + void when_post_login_expect_userService_login_called() throws Exception { final var loginDTO = new UserLoginRequestDTO("email", "password"); - when(userRepository.findFirstByEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword())) - .thenReturn(of(fromEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword()))); + given(userService.login(loginDTO.getEmail(), loginDTO.getPassword())) + .willReturn(of(createNewUser("", loginDTO.getEmail(), loginDTO.getPassword()))); mockMvc.perform(post("/users/login") .contentType(APPLICATION_JSON) .content(objectMapper.writeValueAsString(loginDTO))); - then(userRepository).should(times(1)) - .findFirstByEmailAndPassword(loginDTO.getEmail(), loginDTO.getPassword()); + then(userService).should(times(1)) + .login(loginDTO.getEmail(), loginDTO.getPassword()); } @Test - void when_post_login_expect_valid_response_body() throws Exception { - when(userRepository.findFirstByEmailAndPassword(anyString(), anyString())) - .thenReturn(of(fromEmailAndPassword("email", "password"))); + void when_post_login_expect_valid_response() throws Exception { + when(userService.login(anyString(), anyString())) + .thenReturn(of(createNewUser("username", "email", "password"))); mockMvc.perform(post("/users/login") .contentType(APPLICATION_JSON) @@ -62,4 +65,32 @@ void when_post_login_expect_valid_response_body() throws Exception { .andExpect(jsonPath("$.user.token").hasJsonPath()); } + @Test + void when_post_users_expect_userService_createUser_called() throws Exception { + final var postRequestDTO = new UserPostRequestDTO("username", "email", "password"); + given(userService.createUser(any(User.class))).willReturn(postRequestDTO.toUser()); + + mockMvc.perform(post("/users") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(postRequestDTO))); + + then(userService).should(times(1)).createUser(any(User.class)); + } + + @Test + void when_post_users_expect_valid_response() throws Exception { + when(userService.createUser(any(User.class))) + .thenReturn(createNewUser("username", "email", "password")); + + mockMvc.perform(post("/users") + .contentType(APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new UserLoginRequestDTO("email", "password")))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.user").exists()) + .andExpect(jsonPath("$.user.email").exists()) + .andExpect(jsonPath("$.user.bio").hasJsonPath()) + .andExpect(jsonPath("$.user.image").hasJsonPath()) + .andExpect(jsonPath("$.user.token").hasJsonPath()); + } + } \ No newline at end of file diff --git a/src/test/java/io/github/raeperd/realworld/domain/UserServiceTest.java b/src/test/java/io/github/raeperd/realworld/domain/UserServiceTest.java new file mode 100644 index 0000000..0a09bdf --- /dev/null +++ b/src/test/java/io/github/raeperd/realworld/domain/UserServiceTest.java @@ -0,0 +1,43 @@ +package io.github.raeperd.realworld.domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +@ExtendWith(MockitoExtension.class) +class UserServiceTest { + + private UserService userService; + + @Mock + private UserRepository userRepository; + + @BeforeEach + void initializeService() { + this.userService = new UserService(userRepository); + } + + @Test + void when_login_expect_userRepository_findFirstByEmailAndPassword_called() { + final var email = "email"; + final var password = "password"; + + userService.login(email, password); + + then(userRepository).should(times(1)) + .findFirstByEmailAndPassword(email, password); + } + + @Test + void when_createUser_expect_userRepository_save_called(@Mock User user) { + userService.createUser(user); + + then(userRepository).should(times(1)).save(user); + } + +} diff --git a/src/test/java/io/github/raeperd/realworld/domain/UserTest.java b/src/test/java/io/github/raeperd/realworld/domain/UserTest.java new file mode 100644 index 0000000..253d5c9 --- /dev/null +++ b/src/test/java/io/github/raeperd/realworld/domain/UserTest.java @@ -0,0 +1,20 @@ +package io.github.raeperd.realworld.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class UserTest { + + @Test + void expect_user_has_protected_no_args_constructor() { + class ChildUser extends User { + public ChildUser() { + super(); + } + } + final var childUser = new ChildUser(); + + assertThat(childUser).isInstanceOf(User.class); + } +} \ No newline at end of file From 034c4402c2474a52d1e7de0ae7cc991e8b2dc85a Mon Sep 17 00:00:00 2001 From: raeperd Date: Wed, 14 Apr 2021 21:50:09 +0900 Subject: [PATCH 3/3] [#2] Setup jacoco plugin --- build.gradle | 3 +++ test.gradle | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 test.gradle diff --git a/build.gradle b/build.gradle index 27ca41c..e825439 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'org.springframework.boot' version '2.4.4' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' + id 'jacoco' id "io.freefair.lombok" version "5.3.3.3" id "org.ec4j.editorconfig" version "0.0.3" id "org.sonarqube" version "3.1.1" @@ -23,6 +24,8 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' } +apply from: 'test.gradle' + test { useJUnitPlatform() } diff --git a/test.gradle b/test.gradle new file mode 100644 index 0000000..0de0a95 --- /dev/null +++ b/test.gradle @@ -0,0 +1,74 @@ +test { + useJUnitPlatform() + finalizedBy 'jacocoTestReport' +} + +jacocoTestReport { + reports { + html.enabled true + xml.enabled true + } + finalizedBy 'jacocoTestCoverageVerification' +} + +jacocoTestCoverageVerification { + violationRules { + rule { + element = 'PACKAGE' + + limit { + counter = 'CLASS' + value = 'COVEREDRATIO' + maximum = 1.00 + } + + excludes = [ + 'io.github.raeperd.realworld', + ] + } + rule { + element = "CLASS" + + limit { + counter = 'METHOD' + value = 'COVEREDRATIO' + minimum = 1.00 + } + + excludes = [ + 'io.github.raeperd.realworld.RealWorldApplication' + ] + } + rule { + element = "METHOD" + + limit { + counter = 'INSTRUCTION' + value = 'COVEREDRATIO' + minimum = 1.00 + } + + excludes = [ + 'io.github.raeperd.realworld.RealWorldApplication.main*', + ] + } + rule { + element = "CLASS" + + limit { + counter = 'LINE' + value = 'TOTALCOUNT' + maximum = 100 + } + } + rule { + element = "METHOD" + + limit { + counter = 'LINE' + value = 'TOTALCOUNT' + maximum = 10 + } + } + } +} \ No newline at end of file