From b2907eeab2b909fddf3b2a41147da23feb8e6f49 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:40:46 +0100 Subject: [PATCH] Refactor: Eliminate duplicate code and optimize database queries (#1) * Initial plan * Refactor: Fix duplicate DB queries, add validation, centralize mapping Co-authored-by: Krzykoz <72080194+Krzykoz@users.noreply.github.com> * Add validation and mapper unit tests Co-authored-by: Krzykoz <72080194+Krzykoz@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Krzykoz <72080194+Krzykoz@users.noreply.github.com> --- .../controller/AuthenticationController.java | 5 +- .../controller/UrlController.java | 2 +- .../controller/UserController.java | 3 +- .../dto/AuthenticationRequest.java | 7 +- .../urlshortener/dto/RegisterRequest.java | 9 +- .../kubuski/urlshortener/dto/UrlRequest.java | 9 +- .../kubuski/urlshortener/dto/UserRequest.java | 9 +- .../urlshortener/exception/BaseException.java | 11 +++ .../exception/UrlNotFoundException.java | 2 +- .../exception/UserAlreadyExistsException.java | 2 +- .../exception/UserNotFoundException.java | 2 +- .../urlshortener/mapper/EntityMapper.java | 50 ++++++++++ .../repository/UrlRepository.java | 2 - .../repository/UserRepository.java | 3 + .../service/AuthenticationService.java | 3 +- .../urlshortener/service/UrlService.java | 15 +-- .../urlshortener/service/UserService.java | 9 +- .../urlshortener/dto/DtoValidationTest.java | 99 +++++++++++++++++++ .../urlshortener/mapper/EntityMapperTest.java | 65 ++++++++++++ .../service/AuthenticationServiceTest.java | 2 +- 20 files changed, 276 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/kubuski/urlshortener/exception/BaseException.java create mode 100644 src/main/java/com/kubuski/urlshortener/mapper/EntityMapper.java create mode 100644 src/test/java/com/kubuski/urlshortener/dto/DtoValidationTest.java create mode 100644 src/test/java/com/kubuski/urlshortener/mapper/EntityMapperTest.java diff --git a/src/main/java/com/kubuski/urlshortener/controller/AuthenticationController.java b/src/main/java/com/kubuski/urlshortener/controller/AuthenticationController.java index 00172ec..6037d2a 100644 --- a/src/main/java/com/kubuski/urlshortener/controller/AuthenticationController.java +++ b/src/main/java/com/kubuski/urlshortener/controller/AuthenticationController.java @@ -1,5 +1,6 @@ package com.kubuski.urlshortener.controller; +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -21,13 +22,13 @@ final class AuthenticationController { @PostMapping("/register") @ResponseStatus(HttpStatus.CREATED) - public AuthenticationResponse register(@RequestBody RegisterRequest request) { + public AuthenticationResponse register(@Valid @RequestBody RegisterRequest request) { return authenticationService.register(request); } @PostMapping("/authenticate") @ResponseStatus(HttpStatus.OK) - public AuthenticationResponse authenticate(@RequestBody AuthenticationRequest request) { + public AuthenticationResponse authenticate(@Valid @RequestBody AuthenticationRequest request) { return authenticationService.authenticate(request); } } diff --git a/src/main/java/com/kubuski/urlshortener/controller/UrlController.java b/src/main/java/com/kubuski/urlshortener/controller/UrlController.java index 504f61e..f0deeae 100644 --- a/src/main/java/com/kubuski/urlshortener/controller/UrlController.java +++ b/src/main/java/com/kubuski/urlshortener/controller/UrlController.java @@ -32,7 +32,7 @@ public UrlResponse getOriginalUrl(@PathVariable String shortUrl) { @PutMapping("/{shortUrl}") @ResponseStatus(HttpStatus.OK) public UrlResponse updateOriginalUrl(@PathVariable String shortUrl, - @RequestBody UrlRequest urlRequest) { + @Valid @RequestBody UrlRequest urlRequest) { return urlService.updateOriginalUrl(shortUrl, urlRequest); } diff --git a/src/main/java/com/kubuski/urlshortener/controller/UserController.java b/src/main/java/com/kubuski/urlshortener/controller/UserController.java index 437a4ef..e6487c3 100644 --- a/src/main/java/com/kubuski/urlshortener/controller/UserController.java +++ b/src/main/java/com/kubuski/urlshortener/controller/UserController.java @@ -3,6 +3,7 @@ import com.kubuski.urlshortener.dto.UserRequest; import com.kubuski.urlshortener.dto.UserResponse; import com.kubuski.urlshortener.service.UserService; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -24,7 +25,7 @@ public UserResponse getUserByEmail(@PathVariable String email) { @PostMapping("/register") @ResponseStatus(HttpStatus.CREATED) - public UserResponse registerUser(@RequestBody UserRequest userRequest) { + public UserResponse registerUser(@Valid @RequestBody UserRequest userRequest) { return userService.registerUser(userRequest); } } diff --git a/src/main/java/com/kubuski/urlshortener/dto/AuthenticationRequest.java b/src/main/java/com/kubuski/urlshortener/dto/AuthenticationRequest.java index ad86d63..f189086 100644 --- a/src/main/java/com/kubuski/urlshortener/dto/AuthenticationRequest.java +++ b/src/main/java/com/kubuski/urlshortener/dto/AuthenticationRequest.java @@ -1,4 +1,9 @@ package com.kubuski.urlshortener.dto; -public record AuthenticationRequest(String login, String password) { +import jakarta.validation.constraints.NotBlank; + +public record AuthenticationRequest( + @NotBlank(message = "Login is required") String login, + @NotBlank(message = "Password is required") String password) { + } diff --git a/src/main/java/com/kubuski/urlshortener/dto/RegisterRequest.java b/src/main/java/com/kubuski/urlshortener/dto/RegisterRequest.java index d6df0ee..ea14a0d 100644 --- a/src/main/java/com/kubuski/urlshortener/dto/RegisterRequest.java +++ b/src/main/java/com/kubuski/urlshortener/dto/RegisterRequest.java @@ -1,7 +1,14 @@ package com.kubuski.urlshortener.dto; import com.kubuski.urlshortener.entity.Roles; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; -public record RegisterRequest(String username, String password, String email, Roles role) { +public record RegisterRequest( + @NotBlank(message = "Username is required") String username, + @NotBlank(message = "Password is required") String password, + @NotBlank(message = "Email is required") @Email(message = "Email should be valid") String email, + @NotNull(message = "Role is required") Roles role) { } diff --git a/src/main/java/com/kubuski/urlshortener/dto/UrlRequest.java b/src/main/java/com/kubuski/urlshortener/dto/UrlRequest.java index 05012e1..6bd2548 100644 --- a/src/main/java/com/kubuski/urlshortener/dto/UrlRequest.java +++ b/src/main/java/com/kubuski/urlshortener/dto/UrlRequest.java @@ -1,6 +1,11 @@ package com.kubuski.urlshortener.dto; -import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; + +public record UrlRequest( + @NotBlank(message = "URL is required") + @Pattern(regexp = "^https?://.*", message = "URL must start with http:// or https://") + String url) { -public record UrlRequest(@NotEmpty String url) { } diff --git a/src/main/java/com/kubuski/urlshortener/dto/UserRequest.java b/src/main/java/com/kubuski/urlshortener/dto/UserRequest.java index 5fa6d2d..e3cb200 100644 --- a/src/main/java/com/kubuski/urlshortener/dto/UserRequest.java +++ b/src/main/java/com/kubuski/urlshortener/dto/UserRequest.java @@ -1,7 +1,14 @@ package com.kubuski.urlshortener.dto; import com.kubuski.urlshortener.entity.Roles; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; -public record UserRequest(String username, String password, String email, Roles role) { +public record UserRequest( + @NotBlank(message = "Username is required") String username, + @NotBlank(message = "Password is required") String password, + @NotBlank(message = "Email is required") @Email(message = "Email should be valid") String email, + @NotNull(message = "Role is required") Roles role) { } diff --git a/src/main/java/com/kubuski/urlshortener/exception/BaseException.java b/src/main/java/com/kubuski/urlshortener/exception/BaseException.java new file mode 100644 index 0000000..4ad5336 --- /dev/null +++ b/src/main/java/com/kubuski/urlshortener/exception/BaseException.java @@ -0,0 +1,11 @@ +package com.kubuski.urlshortener.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public abstract class BaseException extends RuntimeException { + protected BaseException(final String message) { + super(message); + } +} diff --git a/src/main/java/com/kubuski/urlshortener/exception/UrlNotFoundException.java b/src/main/java/com/kubuski/urlshortener/exception/UrlNotFoundException.java index 6f09c83..376ac4d 100644 --- a/src/main/java/com/kubuski/urlshortener/exception/UrlNotFoundException.java +++ b/src/main/java/com/kubuski/urlshortener/exception/UrlNotFoundException.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) -public class UrlNotFoundException extends RuntimeException { +public class UrlNotFoundException extends BaseException { public UrlNotFoundException(final String message) { super(message); } diff --git a/src/main/java/com/kubuski/urlshortener/exception/UserAlreadyExistsException.java b/src/main/java/com/kubuski/urlshortener/exception/UserAlreadyExistsException.java index 8a8cb85..ee5f1a8 100644 --- a/src/main/java/com/kubuski/urlshortener/exception/UserAlreadyExistsException.java +++ b/src/main/java/com/kubuski/urlshortener/exception/UserAlreadyExistsException.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.CONFLICT) -public class UserAlreadyExistsException extends RuntimeException { +public class UserAlreadyExistsException extends BaseException { public UserAlreadyExistsException(String message) { super(message); } diff --git a/src/main/java/com/kubuski/urlshortener/exception/UserNotFoundException.java b/src/main/java/com/kubuski/urlshortener/exception/UserNotFoundException.java index 017195f..dd94b3f 100644 --- a/src/main/java/com/kubuski/urlshortener/exception/UserNotFoundException.java +++ b/src/main/java/com/kubuski/urlshortener/exception/UserNotFoundException.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) -public class UserNotFoundException extends RuntimeException { +public class UserNotFoundException extends BaseException { public UserNotFoundException(final String message) { super(message); } diff --git a/src/main/java/com/kubuski/urlshortener/mapper/EntityMapper.java b/src/main/java/com/kubuski/urlshortener/mapper/EntityMapper.java new file mode 100644 index 0000000..b213710 --- /dev/null +++ b/src/main/java/com/kubuski/urlshortener/mapper/EntityMapper.java @@ -0,0 +1,50 @@ +package com.kubuski.urlshortener.mapper; + +import com.kubuski.urlshortener.dto.UrlResponse; +import com.kubuski.urlshortener.dto.UserResponse; +import com.kubuski.urlshortener.entity.Url; +import com.kubuski.urlshortener.entity.User; + +/** + * Utility class for mapping between entities and DTOs. + * Centralizes conversion logic to reduce code duplication. + */ +public final class EntityMapper { + + private EntityMapper() { + // Utility class, prevent instantiation + } + + /** + * Converts a User entity to UserResponse DTO. + * + * @param user the User entity + * @return UserResponse DTO + */ + public static UserResponse toUserResponse(User user) { + return new UserResponse( + user.getId(), + user.getUsername(), + user.getEmail(), + user.getRole() + ); + } + + /** + * Converts a Url entity to UrlResponse DTO. + * + * @param url the Url entity + * @return UrlResponse DTO + */ + public static UrlResponse toUrlResponse(Url url) { + return new UrlResponse( + url.getId(), + url.getOriginalUrl(), + url.getShortUrl(), + url.getCreatedAt(), + url.getUpdatedAt(), + url.getExpirationDate(), + url.getAccessCount() + ); + } +} diff --git a/src/main/java/com/kubuski/urlshortener/repository/UrlRepository.java b/src/main/java/com/kubuski/urlshortener/repository/UrlRepository.java index 000163c..82cf5d0 100644 --- a/src/main/java/com/kubuski/urlshortener/repository/UrlRepository.java +++ b/src/main/java/com/kubuski/urlshortener/repository/UrlRepository.java @@ -8,8 +8,6 @@ import java.util.Optional; public interface UrlRepository extends JpaRepository { - Optional findById(Long id); - Optional findByShortUrlAndDeletedFalse(String shortUrl); List findAllByDeletedTrueAndUpdatedAtBefore(Instant cutoffDate); diff --git a/src/main/java/com/kubuski/urlshortener/repository/UserRepository.java b/src/main/java/com/kubuski/urlshortener/repository/UserRepository.java index 28c420d..a715ab1 100644 --- a/src/main/java/com/kubuski/urlshortener/repository/UserRepository.java +++ b/src/main/java/com/kubuski/urlshortener/repository/UserRepository.java @@ -14,4 +14,7 @@ public interface UserRepository extends JpaRepository { @Query("SELECT u FROM User u WHERE u.email = :login OR u.username = :login") Optional findByEmailOrUsername(@Param("login") String login); + + @Query("SELECT COUNT(u) > 0 FROM User u WHERE u.email = :email OR u.username = :username") + boolean existsByEmailOrUsername(@Param("email") String email, @Param("username") String username); } diff --git a/src/main/java/com/kubuski/urlshortener/service/AuthenticationService.java b/src/main/java/com/kubuski/urlshortener/service/AuthenticationService.java index 228af43..fa99db8 100644 --- a/src/main/java/com/kubuski/urlshortener/service/AuthenticationService.java +++ b/src/main/java/com/kubuski/urlshortener/service/AuthenticationService.java @@ -68,7 +68,6 @@ private void checkIfUserExists(String email, String username) { } private boolean userExists(String email, String username) { - return userRepository.findByEmailOrUsername(email).isPresent() - || userRepository.findByEmailOrUsername(username).isPresent(); + return userRepository.existsByEmailOrUsername(email, username); } } diff --git a/src/main/java/com/kubuski/urlshortener/service/UrlService.java b/src/main/java/com/kubuski/urlshortener/service/UrlService.java index 665f659..6720478 100644 --- a/src/main/java/com/kubuski/urlshortener/service/UrlService.java +++ b/src/main/java/com/kubuski/urlshortener/service/UrlService.java @@ -4,6 +4,7 @@ import com.kubuski.urlshortener.dto.UrlResponse; import com.kubuski.urlshortener.entity.Url; import com.kubuski.urlshortener.exception.UrlNotFoundException; +import com.kubuski.urlshortener.mapper.EntityMapper; import com.kubuski.urlshortener.repository.UrlRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,7 +23,7 @@ public UrlResponse createShortUrl(UrlRequest urlRequest) { Url url = buildUrl(urlRequest); Url savedUrl = urlRepository.save(url); - return toUrlResponse(savedUrl); + return EntityMapper.toUrlResponse(savedUrl); } @Transactional @@ -30,7 +31,7 @@ public UrlResponse getOriginalUrl(String shortUrl) { Url url = findUrlByShortUrl(shortUrl); incrementAccessCount(url); - return toUrlResponse(url); + return EntityMapper.toUrlResponse(url); } @Transactional @@ -38,7 +39,7 @@ public UrlResponse updateOriginalUrl(String shortUrl, UrlRequest urlRequest) { Url url = findUrlByShortUrl(shortUrl); updateUrl(url, urlRequest); - return toUrlResponse(url); + return EntityMapper.toUrlResponse(url); } @Transactional @@ -51,7 +52,7 @@ public void deleteUrl(String shortUrl) { public UrlResponse getUrlStats(String shortUrl) { Url url = findUrlByShortUrl(shortUrl); - return toUrlResponse(url); + return EntityMapper.toUrlResponse(url); } private Url buildUrl(UrlRequest urlRequest) { @@ -80,10 +81,4 @@ private void markUrlAsDeleted(Url url) { private String generateShortCode() { return UUID.randomUUID().toString().substring(0, 8); } - - private UrlResponse toUrlResponse(Url url) { - return new UrlResponse(url.getId(), url.getOriginalUrl(), url.getShortUrl(), - url.getCreatedAt(), url.getUpdatedAt(), url.getExpirationDate(), - url.getAccessCount()); - } } diff --git a/src/main/java/com/kubuski/urlshortener/service/UserService.java b/src/main/java/com/kubuski/urlshortener/service/UserService.java index fa1558f..1012616 100644 --- a/src/main/java/com/kubuski/urlshortener/service/UserService.java +++ b/src/main/java/com/kubuski/urlshortener/service/UserService.java @@ -4,6 +4,7 @@ import com.kubuski.urlshortener.dto.UserResponse; import com.kubuski.urlshortener.entity.User; import com.kubuski.urlshortener.exception.UserNotFoundException; +import com.kubuski.urlshortener.mapper.EntityMapper; import com.kubuski.urlshortener.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; @@ -22,7 +23,7 @@ public UserResponse findByEmail(String email) { User user = userRepository.findByEmail(email).orElseThrow( () -> new UserNotFoundException("User " + email + " not found in Database")); - return toUserResponse(user); + return EntityMapper.toUserResponse(user); } public UserResponse registerUser(UserRequest userRequest) { @@ -30,15 +31,11 @@ public UserResponse registerUser(UserRequest userRequest) { user.setPassword(passwordEncoder.encode(user.getPassword())); userRepository.save(user); - return toUserResponse(user); + return EntityMapper.toUserResponse(user); } private User toUser(UserRequest userRequest) { return User.builder().username(userRequest.username()).password(userRequest.password()) .email(userRequest.email()).role(userRequest.role()).build(); } - - private UserResponse toUserResponse(User user) { - return new UserResponse(user.getId(), user.getUsername(), user.getEmail(), user.getRole()); - } } diff --git a/src/test/java/com/kubuski/urlshortener/dto/DtoValidationTest.java b/src/test/java/com/kubuski/urlshortener/dto/DtoValidationTest.java new file mode 100644 index 0000000..232f323 --- /dev/null +++ b/src/test/java/com/kubuski/urlshortener/dto/DtoValidationTest.java @@ -0,0 +1,99 @@ +package com.kubuski.urlshortener.dto; + +import com.kubuski.urlshortener.entity.Roles; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test class to verify validation constraints on DTOs. + */ +public class DtoValidationTest { + + private static Validator validator; + + @BeforeAll + public static void setUpValidator() { + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + validator = factory.getValidator(); + } + + @Test + public void testUrlRequestValidation() { + UrlRequest validUrl = new UrlRequest("https://example.com"); + Set> violations = validator.validate(validUrl); + assertTrue(violations.isEmpty(), "Valid URL should have no violations"); + + UrlRequest invalidUrl1 = new UrlRequest(""); + violations = validator.validate(invalidUrl1); + assertFalse(violations.isEmpty(), "Empty URL should have violations"); + + UrlRequest invalidUrl2 = new UrlRequest("not-a-url"); + violations = validator.validate(invalidUrl2); + assertFalse(violations.isEmpty(), "Invalid URL format should have violations"); + + UrlRequest invalidUrl3 = new UrlRequest("ftp://example.com"); + violations = validator.validate(invalidUrl3); + assertFalse(violations.isEmpty(), "FTP URL should have violations"); + } + + @Test + public void testUserRequestValidation() { + UserRequest validUser = new UserRequest("user", "password", "user@example.com", Roles.USER); + Set> violations = validator.validate(validUser); + assertTrue(violations.isEmpty(), "Valid user should have no violations"); + + UserRequest invalidUser1 = new UserRequest("", "password", "user@example.com", Roles.USER); + violations = validator.validate(invalidUser1); + assertFalse(violations.isEmpty(), "Empty username should have violations"); + + UserRequest invalidUser2 = new UserRequest("user", "password", "invalid-email", Roles.USER); + violations = validator.validate(invalidUser2); + assertFalse(violations.isEmpty(), "Invalid email should have violations"); + + UserRequest invalidUser3 = new UserRequest("user", "password", "user@example.com", null); + violations = validator.validate(invalidUser3); + assertFalse(violations.isEmpty(), "Null role should have violations"); + } + + @Test + public void testRegisterRequestValidation() { + RegisterRequest validRegister = new RegisterRequest("user", "password", "user@example.com", Roles.USER); + Set> violations = validator.validate(validRegister); + assertTrue(violations.isEmpty(), "Valid register request should have no violations"); + + RegisterRequest invalidRegister1 = new RegisterRequest("", "password", "user@example.com", Roles.USER); + violations = validator.validate(invalidRegister1); + assertFalse(violations.isEmpty(), "Empty username should have violations"); + + RegisterRequest invalidRegister2 = new RegisterRequest("user", "", "user@example.com", Roles.USER); + violations = validator.validate(invalidRegister2); + assertFalse(violations.isEmpty(), "Empty password should have violations"); + + RegisterRequest invalidRegister3 = new RegisterRequest("user", "password", "", Roles.USER); + violations = validator.validate(invalidRegister3); + assertFalse(violations.isEmpty(), "Empty email should have violations"); + } + + @Test + public void testAuthenticationRequestValidation() { + AuthenticationRequest validAuth = new AuthenticationRequest("user", "password"); + Set> violations = validator.validate(validAuth); + assertTrue(violations.isEmpty(), "Valid authentication request should have no violations"); + + AuthenticationRequest invalidAuth1 = new AuthenticationRequest("", "password"); + violations = validator.validate(invalidAuth1); + assertFalse(violations.isEmpty(), "Empty login should have violations"); + + AuthenticationRequest invalidAuth2 = new AuthenticationRequest("user", ""); + violations = validator.validate(invalidAuth2); + assertFalse(violations.isEmpty(), "Empty password should have violations"); + } +} diff --git a/src/test/java/com/kubuski/urlshortener/mapper/EntityMapperTest.java b/src/test/java/com/kubuski/urlshortener/mapper/EntityMapperTest.java new file mode 100644 index 0000000..dbd598f --- /dev/null +++ b/src/test/java/com/kubuski/urlshortener/mapper/EntityMapperTest.java @@ -0,0 +1,65 @@ +package com.kubuski.urlshortener.mapper; + +import com.kubuski.urlshortener.dto.UrlResponse; +import com.kubuski.urlshortener.dto.UserResponse; +import com.kubuski.urlshortener.entity.Roles; +import com.kubuski.urlshortener.entity.Url; +import com.kubuski.urlshortener.entity.User; +import org.junit.jupiter.api.Test; + +import java.time.Instant; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test class for EntityMapper utility. + */ +public class EntityMapperTest { + + @Test + public void testToUserResponse() { + User user = User.builder() + .id(1L) + .username("testuser") + .email("test@example.com") + .role(Roles.USER) + .password("hashedPassword") + .build(); + + UserResponse response = EntityMapper.toUserResponse(user); + + assertAll( + () -> assertEquals(user.getId(), response.id()), + () -> assertEquals(user.getUsername(), response.username()), + () -> assertEquals(user.getEmail(), response.email()), + () -> assertEquals(user.getRole(), response.role()) + ); + } + + @Test + public void testToUrlResponse() { + Instant now = Instant.now(); + Url url = Url.builder() + .id(1L) + .originalUrl("https://example.com") + .shortUrl("abc123") + .createdAt(now) + .updatedAt(now) + .expirationDate(null) + .accessCount(5) + .deleted(false) + .build(); + + UrlResponse response = EntityMapper.toUrlResponse(url); + + assertAll( + () -> assertEquals(url.getId(), response.id()), + () -> assertEquals(url.getOriginalUrl(), response.originalUrl()), + () -> assertEquals(url.getShortUrl(), response.shortUrl()), + () -> assertEquals(url.getCreatedAt(), response.createdAt()), + () -> assertEquals(url.getUpdatedAt(), response.updatedAt()), + () -> assertEquals(url.getExpirationDate(), response.expirationDate()), + () -> assertEquals(url.getAccessCount(), response.accessCount()) + ); + } +} diff --git a/src/test/java/com/kubuski/urlshortener/service/AuthenticationServiceTest.java b/src/test/java/com/kubuski/urlshortener/service/AuthenticationServiceTest.java index 182fab5..747ffd5 100644 --- a/src/test/java/com/kubuski/urlshortener/service/AuthenticationServiceTest.java +++ b/src/test/java/com/kubuski/urlshortener/service/AuthenticationServiceTest.java @@ -63,7 +63,7 @@ public void testRegisterUser() { public void testRegisterUserAlreadyExists() { RegisterRequest request = new RegisterRequest("testuser", "testpassword", "testuser@example.com", Roles.USER); - when(userRepository.findByEmailOrUsername(request.email())).thenReturn(Optional.of(user)); + when(userRepository.existsByEmailOrUsername(request.email(), request.username())).thenReturn(true); assertThrows(UserAlreadyExistsException.class, () -> { authenticationService.register(request);