From cf82f2c63982e56e306f2f4d9261d98d7d3c613e Mon Sep 17 00:00:00 2001 From: russuAV Date: Thu, 13 Mar 2025 13:38:02 +0500 Subject: [PATCH 1/5] 1 commit: - add FilmStorage + UserStorage - add InMemoryFilmStorage + InMemoryUserStorage - add UserService + FilmService + add controllers --- pom.xml | 5 + .../filmorate/controller/FilmController.java | 83 ++++++------- .../filmorate/controller/UserController.java | 116 ++++++------------ .../exception/ConditionsNotMetException.java | 7 ++ .../handler/GlobalExceptionHandler.java | 3 +- .../practicum/filmorate/model/Film.java | 13 ++ .../practicum/filmorate/model/User.java | 7 +- .../filmorate/service/FilmService.java | 81 ++++++++++++ .../filmorate/service/UserService.java | 104 ++++++++++++++++ .../filmorate/storage/FilmStorage.java | 19 +++ .../storage/InMemoryFilmStorage.java | 83 +++++++++++++ .../storage/InMemoryUserStorage.java | 114 +++++++++++++++++ .../filmorate/storage/UserStorage.java | 19 +++ src/main/resources/application.properties | 1 + .../filmorate/service/FilmServiceTest.java | 78 ++++++++++++ .../filmorate/service/UserServiceTest.java | 86 +++++++++++++ .../storage/InMemoryFilmStorageTest.java | 79 ++++++++++++ .../storage/InMemoryUserStorageTest.java | 77 ++++++++++++ 18 files changed, 848 insertions(+), 127 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/UserService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java create mode 100644 src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java diff --git a/pom.xml b/pom.xml index 75a8346..23e262f 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,11 @@ junit-jupiter-api test + + org.zalando + logbook-spring-boot-starter + 3.7.2 + diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 8e4ee87..41ece5e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -3,72 +3,59 @@ import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.exception.NotFoundException; -import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.service.FilmService; +import ru.yandex.practicum.filmorate.storage.FilmStorage; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; @Slf4j @RestController @RequestMapping("/films") public class FilmController { - private final Map films = new HashMap<>(); + private final FilmStorage filmStorage; + private final FilmService filmService; + + public FilmController(FilmStorage filmStorage, FilmService filmService) { + this.filmStorage = filmStorage; + this.filmService = filmService; + } @GetMapping public Collection findAll() { - return films.values(); + return filmStorage.findAll(); } - @PostMapping - public Film create(@Valid @RequestBody Film film) { - log.info("Попытка добавления нового фильма в коллекцию: {}", film.getName()); - if (film.getId() != null && films.containsKey(film.getId())) { - log.error("Ошибка добавления: Фильм уже имеется в коллекции"); - throw new ValidationException("Фильм уже имеется в коллекции"); - } - film.setId(getNextId()); - films.put(film.getId(), film); - log.info("Фильм: '{}', успешно добавлен в коллекцию", film.getName()); - return film; + @GetMapping("/{id}") + public Film getFilmById (@PathVariable Long id) { + return filmStorage.getFilmById(id); } - @PutMapping - public Film update(@Valid @RequestBody Film filmWithNewData) { - if (filmWithNewData.getId() == null || filmWithNewData.getId() == 0) { - throw new ValidationException("id должен быть указан"); - } - log.info("Попытка обновления данных о фильме: '{}'", filmWithNewData.getName()); + @PutMapping("/{id}/like/{userId}") + public void addLike (@PathVariable Long id, + @PathVariable Long userId) { + filmService.addLike(id, userId); + } - Film filmWithOldData = films.get(filmWithNewData.getId()); - if (filmWithOldData == null) { - log.error("Ошибка обновления: фильм не найден"); - throw new NotFoundException("Фильм не найден"); - } - // меняем релиз-дату - if (filmWithNewData.isValidReleaseDate()) { - filmWithOldData.setReleaseDate(filmWithNewData.getReleaseDate()); - } - // меняем название - filmWithOldData.setName(filmWithNewData.getName()); + @DeleteMapping("/{id}/like/{userId}") + public void deleteLike (@PathVariable Long id, + @PathVariable Long userId) { + filmService.deleteLike(id, userId); + } - //меняем описание - filmWithOldData.setDescription(filmWithNewData.getDescription()); + @PostMapping + public Film create(@Valid @RequestBody Film film) { + return filmStorage.create(film); + } - //меняем продолжительность фильма - filmWithOldData.setDuration(filmWithNewData.getDuration()); - log.info("Данные о фильме '{}' успешно обновлены", filmWithOldData.getName()); - return filmWithOldData; + @GetMapping("/popular") + public List getTopFilms (@RequestParam(name = "count", defaultValue = "10") int count) { + return filmService.getTopFilms(count); } - private long getNextId() { - long currentMaxId = films.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; + @PutMapping + public Film update(@Valid @RequestBody Film filmWithNewData) { + return filmStorage.update(filmWithNewData); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 155657b..54951b1 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -2,104 +2,68 @@ import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.exception.NotFoundException; -import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.service.UserService; +import ru.yandex.practicum.filmorate.storage.UserStorage; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.List; @Slf4j @RestController @RequestMapping("/users") public class UserController { - // для пользователей по id - private final Map users = new HashMap<>(); - // для быстрой проверки уникальности email - private final Map usersByEmail = new HashMap<>(); - // для быстрой проверки уникальности login - private final Map usersByLogin = new HashMap<>(); +private final UserStorage userStorage; +private final UserService userService; + public UserController(UserStorage userStorage, UserService userService) { + this.userStorage = userStorage; + this.userService = userService; + } @GetMapping public Collection findAll() { - return users.values(); + return userStorage.findAll(); } - @PostMapping - public User create(@Valid @RequestBody User user) { - log.info("Попытка создания пользователя с email: {} и login: {}", user.getEmail(), user.getLogin()); - if (users.containsKey(user.getId())) { - log.error("Ошибка создания пользователя: id {} уже используется", user.getId()); - throw new ValidationException("Пользователь уже зарегистрирован"); - } - if (usersByEmail.containsKey(user.getEmail())) { - log.error("Ошибка создания пользователя: email {} уже используется", user.getEmail()); - throw new ValidationException("Данный email уже используется"); - } - if (usersByLogin.containsKey(user.getLogin())) { - log.error("Ошибка создания пользователя: login {} уже используется", user.getLogin()); - throw new ValidationException("Данный логин занят"); - } - user.setId(getNextId()); - users.put(user.getId(), user); - usersByEmail.put(user.getEmail(), user); - usersByLogin.put(user.getLogin(), user); - log.info("Пользователь успешно создан с id: {}, email: {}, login: {}", - user.getId(), user.getEmail(), user.getLogin()); - return user; + @GetMapping("/{id}") + public User getUserById (@PathVariable Long id) { + return userStorage.getUserById(id); } - @PutMapping - public User update(@Valid @RequestBody User userWithNewData) { - if (userWithNewData.getId() == null || userWithNewData.getId() == 0) { - throw new ValidationException("id должен быть указан"); - } - log.info("Попытка обновления пользователя с id: {}", userWithNewData.getId()); - - User userWithOldData = users.get(userWithNewData.getId()); - if (userWithOldData == null) { - log.error("Пользователь не найден"); - throw new NotFoundException("Пользователь не найден"); - } - if (!userWithNewData.getEmail().equals(userWithOldData.getEmail()) && - usersByEmail.containsKey(userWithNewData.getEmail())) { - log.error("Ошибка обновления: email {} уже используется", userWithNewData.getEmail()); - throw new ValidationException("Этот e-mail уже используется"); - } + @PutMapping("/{id}/friends/{friendId}") + public void addFriend (@PathVariable Long id, + @PathVariable Long friendId) { + userService.addFriend(id, friendId); + } - // обновляем e-mail - usersByEmail.remove(userWithOldData.getEmail()); - userWithOldData.setEmail(userWithNewData.getEmail()); - usersByEmail.put(userWithOldData.getEmail(), userWithOldData); + @DeleteMapping("/{id}/friends/{friendId}") + public void deleteFriend (@PathVariable Long id, + @PathVariable Long friendId) { + userService.deleteFriend(id, friendId); + } - // обновляем логин - if (!userWithNewData.getLogin().equals(userWithOldData.getLogin()) && - usersByLogin.containsKey(userWithNewData.getLogin())) { - log.error("Ошибка обновления: login {} уже используется", userWithNewData.getLogin()); - throw new ValidationException("Этот логин уже используется"); - } - usersByLogin.remove(userWithOldData.getLogin()); - userWithOldData.setLogin(userWithNewData.getLogin()); - usersByLogin.put(userWithOldData.getLogin(),userWithOldData); + @GetMapping("/{id}/friends") + public List getUserFriends (@PathVariable Long id) { + return userService.getFriends(id); + } - // обновляем имя - userWithOldData.setName(userWithNewData.getName()); + @GetMapping("/{id}/friends/common/{friendId}") + public List getCommonFriends (@PathVariable Long id, + @PathVariable Long friendId) { + return userService.getCommonFriends(id, friendId); + } - // обновляем дату рождения - userWithOldData.setBirthday(userWithNewData.getBirthday()); - log.info("Пользователь с id {} успешно обновлён", userWithOldData.getId()); - return userWithOldData; + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public User create(@Valid @RequestBody User user) { + return userStorage.create(user); } - private long getNextId() { - long currentMaxId = users.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; + @PutMapping + public User update(@Valid @RequestBody User userWithNewData) { + return userStorage.update(userWithNewData); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java new file mode 100644 index 0000000..c653ae4 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ConditionsNotMetException.java @@ -0,0 +1,7 @@ +package ru.yandex.practicum.filmorate.exception; + +public class ConditionsNotMetException extends RuntimeException { + public ConditionsNotMetException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java index 845f060..f0d7759 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java @@ -3,6 +3,7 @@ import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import ru.yandex.practicum.filmorate.dto.ErrorResponse; @@ -26,7 +27,7 @@ public ResponseEntity handleNotFound(NotFoundException e, HttpSer return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); } - @ExceptionHandler(ValidationException.class) + @ExceptionHandler({ValidationException.class, MethodArgumentNotValidException.class}) public ResponseEntity handleValidation(ValidationException e, HttpServletRequest request) { ErrorResponse errorResponse = new ErrorResponse( LocalDateTime.now(), diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 4b61a5a..8aebb70 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -2,12 +2,25 @@ import jakarta.validation.constraints.*; import lombok.Data; +import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Data +@RequiredArgsConstructor public class Film { private Long id; + private Set likes = new HashSet<>(); + + public Film(Long id, LocalDate releaseDate, String name, String description, int duration) { + this.id = id; + this.releaseDate = releaseDate; + this.name = name; + this.description = description; + this.duration = duration; + } @NotNull private LocalDate releaseDate; diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 5d62895..73a672f 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -4,14 +4,17 @@ import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.*; import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; @Data -@NoArgsConstructor +@RequiredArgsConstructor public class User { private Long id; + private Set friends = new HashSet<>(); @NotBlank(message = "Электронная почта не может быть пустой") @Email(message = "Электронная почта должна быть корректной и содержать символ '@'") diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java new file mode 100644 index 0000000..3d4188d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -0,0 +1,81 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.FilmStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.Comparator; +import java.util.List; + +@Slf4j +@Service +public class FilmService { + private final FilmStorage filmStorage; + private final UserStorage userStorage; + + @Autowired + public FilmService(FilmStorage filmStorage, UserStorage userStorage) { + this.filmStorage = filmStorage; + this.userStorage = userStorage; + } + + public void addLike (Long filmId, Long userId) { + log.debug("Попытка добавить лайк фильму {} от пользователя {}.", filmId, userId); + validateFilmAndUserExist(filmId, userId); + Film film = filmStorage.getFilmById(filmId); + + if (!film.getLikes().add(userId)) { + log.error("Пользователь с id {} уже добавил лайк фильму {}.", userId, filmId); + throw new ValidationException("Данный пользователь уже добавлял лайк этому фильму!"); + } + log.info("Пользователь {} поставил лайк фильму {}.", userId, filmId); + } + + public void deleteLike (Long filmId, Long userId) { + log.debug("Попытка удалить лайк у фильма {} от пользователя {}.", filmId, userId); + validateFilmAndUserExist(filmId, userId); + Film film = filmStorage.getFilmById(filmId); + + if (!film.getLikes().remove(userId)) { + log.error("Пользователь с id {} не ставил лайк фильму {}.", userId, filmId); + throw new ValidationException("Этот пользователь не ставил лайк данному фильму"); + } + log.info("Пользователь {} удалил лайк у фильма {}.", userId, filmId); + } + + public List getTopFilms (int count) { + log.debug("Запрос на получение топ фильмов"); + List topFilms = filmStorage.findAll().stream() + .sorted(Comparator.comparingInt(film -> -film.getLikes().size())) + .limit(count) + .toList(); + log.info("Выведен список из {} топ фильмов", topFilms.size()); + return topFilms; + } + + public void validateFilmAndUserExist (Long filmId, Long userId) { + log.trace("Валидация существования фильма с id {} и пользователя с id {}", filmId, userId); + if (filmId == null || userId == null) { + log.error("Оба идентификатора (filmId и userId) должны быть указаны"); + throw new ValidationException("Id должен быть указан"); + } + try { + filmStorage.getFilmById(filmId); + } catch (NotFoundException e) { + log.error("Фильм с id {} не найден.", filmId); + throw e; + } + try { + userStorage.getUserById(userId); + } catch (NotFoundException e) { + log.error("Пользователь с id {} не найден.", userId); + throw e; + } + log.trace("Валидация успешна для фильма с id {} и пользователя с id {}", filmId, userId); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java new file mode 100644 index 0000000..0246064 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -0,0 +1,104 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.exception.ConditionsNotMetException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Slf4j +@Service +public class UserService { + private final UserStorage userStorage; + + @Autowired + public UserService(UserStorage userStorage) { + this.userStorage = userStorage; + } + + public void addFriend(Long id, Long friendId) { + log.debug("Попытка пользователя {} добавить в друзья пользователя {}", id, friendId); + User[] users = validateAndGetUsers(id, friendId); + User user1 = users[0]; + User user2 = users[1]; + + if (user1.getFriends().contains(friendId)) { + log.error("Пользователь с id {} уже имеется в друзьях у пользователя {}", friendId, id); + throw new ValidationException("Данный друг уже имеется в списке друзей!"); + } + user1.getFriends().add(friendId); + user2.getFriends().add(id); + + log.info("Пользователь {} успешно добавил в друзья пользователя {}", id, friendId); + } + + public List getFriends (Long id) { + log.debug("Попытка получить список друзей пользователя с id {}", id); + User user = userStorage.getUserById(id); + Set friendIds = user.getFriends(); + + log.info("Получен список друзей пользователя с id {}", id); + return friendIds.stream() + .map(userStorage::getUserById) + .toList(); + } + + public List getCommonFriends (Long id, Long friendsId) { + log.debug("Запрос на получение списка общих друзей"); + User[] users = validateAndGetUsers(id, friendsId); + User user1 = users[0]; + User user2 = users[1]; + + Set friendIdsUser1 = user1.getFriends(); + Set friendsIdsUser2 = user2.getFriends(); + + Set commonFriends = new HashSet<>(friendIdsUser1); + commonFriends.retainAll(friendsIdsUser2); + + log.info("Выведен список общих друзей"); + return commonFriends.stream() + .map(userStorage::getUserById) + .toList(); + } + + public void deleteFriend (Long id, Long friendsId) { + log.debug("Попытка пользователя {} удалить из друзей пользователя {}", id, friendsId); + User[] users = validateAndGetUsers(id, friendsId); + User user1 = users[0]; + User user2 = users[1]; + + if (!user1.getFriends().contains(friendsId)) { + log.warn("Пользователь с id {} отсутствует в списке друзей у пользователя {}", friendsId, id); + return; + } + + user1.getFriends().remove(friendsId); + user2.getFriends().remove(id); + + log.info("Пользователь {} успешно удалил из друзей пользователя {}", id, friendsId); + } + + private User[] validateAndGetUsers (Long id, Long friendsId) { + log.trace("Валидация существования пользователей с id {} и {}", id, friendsId); + if (id == null || friendsId == null) { + log.error("Отсутствует информация об ID"); + throw new ConditionsNotMetException("Id должен быть указан"); + } + if (id.equals(friendsId)) { + log.error("ID совпадают, неверно указаны идентификаторы пользователей"); + throw new ValidationException("Личный id, и id друга совпадают. Неверный ввод данных"); + } + + User user1 = userStorage.getUserById(id); + User user2 = userStorage.getUserById(friendsId); + + log.trace("Валидация пользователей с ID {} и {} прошла успешно", id, friendsId); + return new User[]{user1, user2}; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java new file mode 100644 index 0000000..3fccb00 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -0,0 +1,19 @@ +package ru.yandex.practicum.filmorate.storage; + +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; + +public interface FilmStorage { + + Collection findAll(); + + Film getFilmById(Long id); + + Film create (Film film); + + Film update (Film filmWithNewData); + + long getNextId(); +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java new file mode 100644 index 0000000..ddab03f --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -0,0 +1,83 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Component +public class InMemoryFilmStorage implements FilmStorage { + private final Map films = new HashMap<>(); + + @Override + public Collection findAll() { + return films.values(); + } + + @Override + public Film getFilmById(Long id) { + log.debug("Попытка получить фильм с id {}.", id); + Film film = films.get(id); + if (film == null) { + log.error("Фильм с id {} не найден.", id); + throw new NotFoundException("Фильм с id " + id + " не найден."); + } + log.info("Получен фильм с id {}.", id); + return film; + } + + @Override + public Film create(Film film) { + log.info("Попытка добавления нового фильма в коллекцию: {}", film.getName()); + if (film.getId() != null && films.containsKey(film.getId())) { + log.error("Ошибка добавления: Фильм уже имеется в коллекции"); + throw new ValidationException("Фильм уже имеется в коллекции"); + } + film.setId(getNextId()); + films.put(film.getId(), film); + log.info("Фильм: '{}', успешно добавлен в коллекцию", film.getName()); + return film; } + + @Override + public Film update(Film filmWithNewData) { + if (filmWithNewData.getId() == null || filmWithNewData.getId() == 0) { + throw new ValidationException("id должен быть указан"); + } + log.info("Попытка обновления данных о фильме: '{}'", filmWithNewData.getName()); + + Film filmWithOldData = films.get(filmWithNewData.getId()); + if (filmWithOldData == null) { + log.error("Ошибка обновления: фильм не найден"); + throw new NotFoundException("Фильм не найден"); + } + // меняем релиз-дату + if (filmWithNewData.isValidReleaseDate()) { + filmWithOldData.setReleaseDate(filmWithNewData.getReleaseDate()); + } + // меняем название + filmWithOldData.setName(filmWithNewData.getName()); + + //меняем описание + filmWithOldData.setDescription(filmWithNewData.getDescription()); + + //меняем продолжительность фильма + filmWithOldData.setDuration(filmWithNewData.getDuration()); + log.info("Данные о фильме '{}' успешно обновлены", filmWithOldData.getName()); + return filmWithOldData; + } + + @Override + public long getNextId() { + long currentMaxId = films.keySet() + .stream() + .mapToLong(id -> id) + .max() + .orElse(0); + return ++currentMaxId; } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java new file mode 100644 index 0000000..7317e8c --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -0,0 +1,114 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.*; + +@Slf4j +@Component +public class InMemoryUserStorage implements UserStorage { + // для пользователей по id + private final Map users = new HashMap<>(); + // для быстрой проверки уникальности email + private final Map usersByEmail = new HashMap<>(); + // для быстрой проверки уникальности login + private final Map usersByLogin = new HashMap<>(); + + @Override + public Collection findAll() { + return users.values(); + } + + @Override + public User getUserById(Long id) { + log.debug("Попытка полючить пользователя с id {}.", id); + User user = users.get(id); + if (user == null) { + log.error("Пользователь с id {} не найден.", id); + throw new NotFoundException("Пользователь с id " + id + " не найден."); + } + log.info("Пользователь с id {} получен.", id); + return user; + } + + @Override + public User create(User user) { + log.info("Попытка создания пользователя с email: {} и login: {}", user.getEmail(), user.getLogin()); + if (users.containsKey(user.getId())) { + log.error("Ошибка создания пользователя: id {} уже используется", user.getId()); + throw new ValidationException("Пользователь уже зарегистрирован"); + } + if (usersByEmail.containsKey(user.getEmail())) { + log.error("Ошибка создания пользователя: email {} уже используется", user.getEmail()); + throw new ValidationException("Данный email уже используется"); + } + if (usersByLogin.containsKey(user.getLogin())) { + log.error("Ошибка создания пользователя: login {} уже используется", user.getLogin()); + throw new ValidationException("Данный логин занят"); + } + user.setId(getNextId()); + users.put(user.getId(), user); + usersByEmail.put(user.getEmail(), user); + usersByLogin.put(user.getLogin(), user); + + log.info("Пользователь успешно создан с id: {}, email: {}, login: {}", + user.getId(), user.getEmail(), user.getLogin()); + return user; + } + + @Override + public User update(User userWithNewData) { + log.info("Попытка обновления пользователя с id: {}", userWithNewData.getId()); + + if (userWithNewData.getId() == null || userWithNewData.getId() == 0) { + throw new ValidationException("id должен быть указан"); + } + User userWithOldData = users.get(userWithNewData.getId()); + if (userWithOldData == null) { + log.error("Пользователь не найден"); + throw new NotFoundException("Пользователь не найден"); + } + if (!userWithNewData.getEmail().equals(userWithOldData.getEmail()) && + usersByEmail.containsKey(userWithNewData.getEmail())) { + log.error("Ошибка обновления: email {} уже используется", userWithNewData.getEmail()); + throw new ValidationException("Этот e-mail уже используется"); + } + + // обновляем e-mail + usersByEmail.remove(userWithOldData.getEmail()); + userWithOldData.setEmail(userWithNewData.getEmail()); + usersByEmail.put(userWithOldData.getEmail(), userWithOldData); + + // обновляем логин + if (!userWithNewData.getLogin().equals(userWithOldData.getLogin()) && + usersByLogin.containsKey(userWithNewData.getLogin())) { + log.error("Ошибка обновления: login {} уже используется", userWithNewData.getLogin()); + throw new ValidationException("Этот логин уже используется"); + } + usersByLogin.remove(userWithOldData.getLogin()); + userWithOldData.setLogin(userWithNewData.getLogin()); + usersByLogin.put(userWithOldData.getLogin(), userWithOldData); + + // обновляем имя + userWithOldData.setName(userWithNewData.getName()); + + // обновляем дату рождения + userWithOldData.setBirthday(userWithNewData.getBirthday()); + log.info("Пользователь с id {} успешно обновлён", userWithOldData.getId()); + return userWithOldData; + } + + @Override + public long getNextId() { + long currentMaxId = users.keySet() + .stream() + .mapToLong(id -> id) + .max() + .orElse(0); + return ++currentMaxId; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java new file mode 100644 index 0000000..8a65d1d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -0,0 +1,19 @@ +package ru.yandex.practicum.filmorate.storage; + +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; + +public interface UserStorage { + + Collection findAll (); + + User getUserById(Long id); + + User create (User user); + + User update (User userWithNewData); + + long getNextId(); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4c00e40..36f6ba6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ server.port=8080 +logging.level.org.zalando.logbook: TRACE diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java b/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java new file mode 100644 index 0000000..e058d5e --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/service/FilmServiceTest.java @@ -0,0 +1,78 @@ +package ru.yandex.practicum.filmorate.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.FilmStorage; +import ru.yandex.practicum.filmorate.storage.InMemoryFilmStorage; +import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class FilmServiceTest { + private FilmStorage filmStorage; + private FilmService filmService; + private UserStorage userStorage; + + @BeforeEach + void setUp() { + filmStorage = new InMemoryFilmStorage(); + userStorage = new InMemoryUserStorage(); + filmService = new FilmService(filmStorage, userStorage); + } + + @Test + void addLike() { + Film film = new Film(1L, LocalDate.of(1997, 1, 26), + "test", "description", 120); + + User user = userStorage.create(new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997,1,26))); + filmStorage.create(film); + filmService.addLike(film.getId(), user.getId()); + + assertEquals(1, filmStorage.getFilmById(film.getId()).getLikes().size()); + } + + @Test + void deleteLike() { + Film film = new Film(1L, LocalDate.of(1997, 1, 26), + "test", "description", 120); + + User user = userStorage.create(new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997,1,26))); + filmStorage.create(film); + filmService.addLike(film.getId(), user.getId()); + filmService.deleteLike(film.getId(), user.getId()); + + assertEquals(0, filmStorage.getFilmById(film.getId()).getLikes().size()); + + } + + @Test + void getTopFilms() { + Film film1 = new Film(1L, LocalDate.of(1997, 1, 26), + "test1", "description1", 120); + Film film2 = new Film(2L, LocalDate.of(1997, 1, 26), + "test2", "description2", 120); + + User user = userStorage.create(new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997,1,26))); + + filmStorage.create(film1); + filmStorage.create(film2); + + filmService.addLike(film1.getId(), user.getId()); + + List topFilms = filmService.getTopFilms(2); + + assertEquals(2, topFilms.size()); + assertEquals("test1", topFilms.getFirst().getName()); + + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java b/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java new file mode 100644 index 0000000..daa3378 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java @@ -0,0 +1,86 @@ +package ru.yandex.practicum.filmorate.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.InMemoryUserStorage; +import ru.yandex.practicum.filmorate.storage.UserStorage; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class UserServiceTest { + private UserService userService; + private UserStorage userStorage; + + @BeforeEach + void setup() { + userStorage = new InMemoryUserStorage() { + }; + userService = new UserService(userStorage); + } + + @Test + void shouldAddFriend() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 27)); + userStorage.create(user1); + userStorage.create(user2); + + userService.addFriend(1L, 2L); + assertTrue(user1.getFriends().contains(2L)); + assertTrue(user2.getFriends().contains(1L)); + } + + @Test + void shouldGetFriends() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + userStorage.create(user1); + User theSameUser = userStorage.getUserById(1L); + assertEquals(user1, theSameUser); + } + + @Test + void getCommonFriends() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 27)); + User user3 = new User(3L, "user3@email.com", "user3", "user3", + LocalDate.of(1997, 01, 28)); + userStorage.create(user1); + userStorage.create(user2); + userStorage.create(user3); + + userService.addFriend(user1.getId(), user3.getId()); + userService.addFriend(user2.getId(), user3.getId()); + + List commonFriends= userService.getCommonFriends(user1.getId(), user2.getId()); + assertTrue(commonFriends.contains(user3)); + } + + @Test + void deleteFriend() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 27)); + + userStorage.create(user1); + userStorage.create(user2); + + userService.addFriend(user1.getId(), user2.getId()); + userService.deleteFriend(user1.getId(), user2.getId()); + + assertFalse(user1.getFriends().contains(user2.getId())); + assertFalse(user2.getFriends().contains(user1.getId())); + + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java new file mode 100644 index 0000000..bcc1671 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java @@ -0,0 +1,79 @@ +package ru.yandex.practicum.filmorate.storage; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.*; + +class InMemoryFilmStorageTest { +private FilmStorage filmStorage; + +@BeforeEach + void setUp() { + filmStorage = new InMemoryFilmStorage() { + }; + } + + + @Test + void findAll() { + Film film1 = new Film(1L, LocalDate.of(1997, 1, 26), + "test1", "description1", 120); + Film film2 = new Film(2L, LocalDate.of(1997, 1, 26), + "test2", "description2", 120); + filmStorage.create(film1); + filmStorage.create(film2); + + assertEquals(2, filmStorage.findAll().size()); + assertEquals("test1", filmStorage.getFilmById(1L).getName()); + assertEquals("test2", filmStorage.getFilmById(2L).getName()); + } + + @Test + void getFilmById() { + Film film1 = new Film(1L, LocalDate.of(1997, 1, 26), + "test1", "description1", 120); + filmStorage.create(film1); + + assertEquals(film1, filmStorage.getFilmById(1L)); + } + + @Test + void getFilmByIdShouldThrowException() { + Exception exception = assertThrows(NotFoundException.class, () -> { + filmStorage.getFilmById(1L); + }); + assertEquals("Фильм с id 1 не найден.", exception.getMessage()); + } + + @Test + void create() { + Film film1 = new Film(1L, LocalDate.of(1997, 1, 26), + "test1", "description1", 120); + filmStorage.create(film1); + + assertEquals(1, filmStorage.findAll().size()); + assertEquals("test1", filmStorage.getFilmById(1L).getName()); + } + + @Test + void update() { + Film film1 = new Film(1L, LocalDate.of(1997, 1, 26), + "test1", "description1", 120); + + filmStorage.create(film1); + film1.setName("newTest1"); + film1.setDescription("newDescription1"); + film1.setDuration(130); + + filmStorage.update(film1); + + assertEquals("newTest1", filmStorage.getFilmById(1L).getName()); + assertEquals("newDescription1", filmStorage.getFilmById(1L).getDescription()); + assertEquals(130, filmStorage.getFilmById(1L).getDuration()); + } +} \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java new file mode 100644 index 0000000..7fc1192 --- /dev/null +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java @@ -0,0 +1,77 @@ +package ru.yandex.practicum.filmorate.storage; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.User; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.*; + +class InMemoryUserStorageTest { + private UserStorage userStorage; + + + @BeforeEach + void setUp() { + userStorage = new InMemoryUserStorage(); + } + + @Test + void findAll() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 27)); + userStorage.create(user1); + userStorage.create(user2); + + assertEquals(2, userStorage.findAll().size()); + } + + @Test + void getUserById() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + assertEquals(user1, userStorage.getUserById(user1.getId())); + } + + @Test + void getUserByIdShouldThrowException() { + Exception exception = assertThrows(NotFoundException.class, () -> { + userStorage.getUserById(1L); + }); + assertEquals("Пользователь с id 1 не найден.", exception.getMessage()); + } + + @Test + void create() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 27)); + userStorage.create(user1); + userStorage.create(user2); + + assertEquals(user1, userStorage.getUserById(1L)); + assertEquals(user2, userStorage.getUserById(2L)); + assertEquals("user1", userStorage.getUserById(1L).getName()); + } + + @Test + void update() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + user1.setName("newUser1"); + user1.setLogin("newLogin1"); + userStorage.update(user1); + + assertEquals("newUser1", userStorage.getUserById(user1.getId()).getName()); + assertEquals("newLogin1", userStorage.getUserById(user1.getId()).getLogin()); + } +} \ No newline at end of file From 84d6a1411352ae276b1231e2ffeafeab21e6c00e Mon Sep 17 00:00:00 2001 From: russuAV Date: Thu, 13 Mar 2025 13:59:17 +0500 Subject: [PATCH 2/5] 2 commit: - delete whitespaces --- .../filmorate/controller/FilmController.java | 12 ++++++------ .../filmorate/controller/UserController.java | 12 ++++++------ .../practicum/filmorate/service/FilmService.java | 8 ++++---- .../practicum/filmorate/service/UserService.java | 8 ++++---- .../practicum/filmorate/storage/FilmStorage.java | 5 ++--- .../practicum/filmorate/storage/UserStorage.java | 7 +++---- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 41ece5e..766fff2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -28,19 +28,19 @@ public Collection findAll() { } @GetMapping("/{id}") - public Film getFilmById (@PathVariable Long id) { + public Film getFilmById(@PathVariable Long id) { return filmStorage.getFilmById(id); } @PutMapping("/{id}/like/{userId}") - public void addLike (@PathVariable Long id, - @PathVariable Long userId) { + public void addLike(@PathVariable Long id, + @PathVariable Long userId) { filmService.addLike(id, userId); } @DeleteMapping("/{id}/like/{userId}") - public void deleteLike (@PathVariable Long id, - @PathVariable Long userId) { + public void deleteLike(@PathVariable Long id, + @PathVariable Long userId) { filmService.deleteLike(id, userId); } @@ -50,7 +50,7 @@ public Film create(@Valid @RequestBody Film film) { } @GetMapping("/popular") - public List getTopFilms (@RequestParam(name = "count", defaultValue = "10") int count) { + public List getTopFilms(@RequestParam(name = "count", defaultValue = "10") int count) { return filmService.getTopFilms(count); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 54951b1..295adf2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -29,29 +29,29 @@ public Collection findAll() { } @GetMapping("/{id}") - public User getUserById (@PathVariable Long id) { + public User getUserById(@PathVariable Long id) { return userStorage.getUserById(id); } @PutMapping("/{id}/friends/{friendId}") - public void addFriend (@PathVariable Long id, - @PathVariable Long friendId) { + public void addFriend(@PathVariable Long id, + @PathVariable Long friendId) { userService.addFriend(id, friendId); } @DeleteMapping("/{id}/friends/{friendId}") - public void deleteFriend (@PathVariable Long id, + public void deleteFriend(@PathVariable Long id, @PathVariable Long friendId) { userService.deleteFriend(id, friendId); } @GetMapping("/{id}/friends") - public List getUserFriends (@PathVariable Long id) { + public List getUserFriends(@PathVariable Long id) { return userService.getFriends(id); } @GetMapping("/{id}/friends/common/{friendId}") - public List getCommonFriends (@PathVariable Long id, + public List getCommonFriends(@PathVariable Long id, @PathVariable Long friendId) { return userService.getCommonFriends(id, friendId); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 3d4188d..7ddae21 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -24,7 +24,7 @@ public FilmService(FilmStorage filmStorage, UserStorage userStorage) { this.userStorage = userStorage; } - public void addLike (Long filmId, Long userId) { + public void addLike(Long filmId, Long userId) { log.debug("Попытка добавить лайк фильму {} от пользователя {}.", filmId, userId); validateFilmAndUserExist(filmId, userId); Film film = filmStorage.getFilmById(filmId); @@ -36,7 +36,7 @@ public void addLike (Long filmId, Long userId) { log.info("Пользователь {} поставил лайк фильму {}.", userId, filmId); } - public void deleteLike (Long filmId, Long userId) { + public void deleteLike(Long filmId, Long userId) { log.debug("Попытка удалить лайк у фильма {} от пользователя {}.", filmId, userId); validateFilmAndUserExist(filmId, userId); Film film = filmStorage.getFilmById(filmId); @@ -48,7 +48,7 @@ public void deleteLike (Long filmId, Long userId) { log.info("Пользователь {} удалил лайк у фильма {}.", userId, filmId); } - public List getTopFilms (int count) { + public List getTopFilms(int count) { log.debug("Запрос на получение топ фильмов"); List topFilms = filmStorage.findAll().stream() .sorted(Comparator.comparingInt(film -> -film.getLikes().size())) @@ -58,7 +58,7 @@ public List getTopFilms (int count) { return topFilms; } - public void validateFilmAndUserExist (Long filmId, Long userId) { + public void validateFilmAndUserExist(Long filmId, Long userId) { log.trace("Валидация существования фильма с id {} и пользователя с id {}", filmId, userId); if (filmId == null || userId == null) { log.error("Оба идентификатора (filmId и userId) должны быть указаны"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 0246064..240dbdc 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -38,7 +38,7 @@ public void addFriend(Long id, Long friendId) { log.info("Пользователь {} успешно добавил в друзья пользователя {}", id, friendId); } - public List getFriends (Long id) { + public List getFriends(Long id) { log.debug("Попытка получить список друзей пользователя с id {}", id); User user = userStorage.getUserById(id); Set friendIds = user.getFriends(); @@ -49,7 +49,7 @@ public List getFriends (Long id) { .toList(); } - public List getCommonFriends (Long id, Long friendsId) { + public List getCommonFriends(Long id, Long friendsId) { log.debug("Запрос на получение списка общих друзей"); User[] users = validateAndGetUsers(id, friendsId); User user1 = users[0]; @@ -67,7 +67,7 @@ public List getCommonFriends (Long id, Long friendsId) { .toList(); } - public void deleteFriend (Long id, Long friendsId) { + public void deleteFriend(Long id, Long friendsId) { log.debug("Попытка пользователя {} удалить из друзей пользователя {}", id, friendsId); User[] users = validateAndGetUsers(id, friendsId); User user1 = users[0]; @@ -84,7 +84,7 @@ public void deleteFriend (Long id, Long friendsId) { log.info("Пользователь {} успешно удалил из друзей пользователя {}", id, friendsId); } - private User[] validateAndGetUsers (Long id, Long friendsId) { + private User[] validateAndGetUsers(Long id, Long friendsId) { log.trace("Валидация существования пользователей с id {} и {}", id, friendsId); if (id == null || friendsId == null) { log.error("Отсутствует информация об ID"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java index 3fccb00..880018d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.storage; -import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.Film; import java.util.Collection; @@ -11,9 +10,9 @@ public interface FilmStorage { Film getFilmById(Long id); - Film create (Film film); + Film create(Film film); - Film update (Film filmWithNewData); + Film update(Film filmWithNewData); long getNextId(); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java index 8a65d1d..ecbf852 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -1,19 +1,18 @@ package ru.yandex.practicum.filmorate.storage; -import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.User; import java.util.Collection; public interface UserStorage { - Collection findAll (); + Collection findAll(); User getUserById(Long id); - User create (User user); + User create(User user); - User update (User userWithNewData); + User update(User userWithNewData); long getNextId(); } From 0353665b8de24baad64d846f067fd6893205524d Mon Sep 17 00:00:00 2001 From: russuAV Date: Thu, 13 Mar 2025 14:04:10 +0500 Subject: [PATCH 3/5] 3 commit: - delete checkstyle errors --- .../yandex/practicum/filmorate/FilmorateApplication.java | 3 +-- .../practicum/filmorate/controller/UserController.java | 2 +- .../exception/handler/GlobalExceptionHandler.java | 2 +- .../java/ru/yandex/practicum/filmorate/model/Film.java | 2 +- .../java/ru/yandex/practicum/filmorate/model/User.java | 2 +- .../yandex/practicum/filmorate/service/FilmService.java | 2 +- .../yandex/practicum/filmorate/storage/FilmStorage.java | 2 +- .../practicum/filmorate/storage/InMemoryFilmStorage.java | 8 +++++--- .../practicum/filmorate/storage/InMemoryUserStorage.java | 2 +- .../yandex/practicum/filmorate/storage/UserStorage.java | 2 +- 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java index dca451b..8f860a2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java +++ b/src/main/java/ru/yandex/practicum/filmorate/FilmorateApplication.java @@ -8,5 +8,4 @@ public class FilmorateApplication { public static void main(String[] args) { SpringApplication.run(FilmorateApplication.class, args); } - -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 295adf2..954ba1c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -66,4 +66,4 @@ public User create(@Valid @RequestBody User user) { public User update(@Valid @RequestBody User userWithNewData) { return userStorage.update(userWithNewData); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java index f0d7759..4281222 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java @@ -50,4 +50,4 @@ public ResponseEntity handleOtherExceptions(Exception e, HttpServ ); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 8aebb70..987b732 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -41,4 +41,4 @@ public boolean isValidReleaseDate() { LocalDate minReleaseDate = LocalDate.of(1895,12,28); return !releaseDate.isBefore(minReleaseDate); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 73a672f..1918db7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -46,4 +46,4 @@ public User(@JsonProperty("id") Long id, public void setName(String name) { this.name = (name == null || name.isBlank()) ? this.login : name; } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 7ddae21..9a6435a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -78,4 +78,4 @@ public void validateFilmAndUserExist(Long filmId, Long userId) { } log.trace("Валидация успешна для фильма с id {} и пользователя с id {}", filmId, userId); } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java index 880018d..0ab484c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmStorage.java @@ -15,4 +15,4 @@ public interface FilmStorage { Film update(Film filmWithNewData); long getNextId(); -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java index ddab03f..1eb4bfe 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -42,7 +42,8 @@ public Film create(Film film) { film.setId(getNextId()); films.put(film.getId(), film); log.info("Фильм: '{}', успешно добавлен в коллекцию", film.getName()); - return film; } + return film; + } @Override public Film update(Film filmWithNewData) { @@ -79,5 +80,6 @@ public long getNextId() { .mapToLong(id -> id) .max() .orElse(0); - return ++currentMaxId; } -} + return ++currentMaxId; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index 7317e8c..f4e3b35 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -111,4 +111,4 @@ public long getNextId() { .orElse(0); return ++currentMaxId; } -} +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java index ecbf852..4b011ae 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserStorage.java @@ -15,4 +15,4 @@ public interface UserStorage { User update(User userWithNewData); long getNextId(); -} +} \ No newline at end of file From 38d5f03ffba8596842c04ca3a97fe7a142dad945 Mon Sep 17 00:00:00 2001 From: russuAV Date: Thu, 13 Mar 2025 14:16:05 +0500 Subject: [PATCH 4/5] 4 commit: - delete checkstyle errors --- .../exception/handler/GlobalExceptionHandler.java | 3 ++- .../practicum/filmorate/storage/InMemoryUserStorage.java | 8 ++++---- .../practicum/filmorate/service/UserServiceTest.java | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java index 4281222..f56b3fa 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/handler/GlobalExceptionHandler.java @@ -28,7 +28,8 @@ public ResponseEntity handleNotFound(NotFoundException e, HttpSer } @ExceptionHandler({ValidationException.class, MethodArgumentNotValidException.class}) - public ResponseEntity handleValidation(ValidationException e, HttpServletRequest request) { + public ResponseEntity handleValidation( + ValidationException e, HttpServletRequest request) { ErrorResponse errorResponse = new ErrorResponse( LocalDateTime.now(), HttpStatus.BAD_REQUEST.value(), diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index f4e3b35..e0a0feb 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -72,8 +72,8 @@ public User update(User userWithNewData) { log.error("Пользователь не найден"); throw new NotFoundException("Пользователь не найден"); } - if (!userWithNewData.getEmail().equals(userWithOldData.getEmail()) && - usersByEmail.containsKey(userWithNewData.getEmail())) { + if (!userWithNewData.getEmail().equals(userWithOldData.getEmail()) + && usersByEmail.containsKey(userWithNewData.getEmail())) { log.error("Ошибка обновления: email {} уже используется", userWithNewData.getEmail()); throw new ValidationException("Этот e-mail уже используется"); } @@ -84,8 +84,8 @@ public User update(User userWithNewData) { usersByEmail.put(userWithOldData.getEmail(), userWithOldData); // обновляем логин - if (!userWithNewData.getLogin().equals(userWithOldData.getLogin()) && - usersByLogin.containsKey(userWithNewData.getLogin())) { + if (!userWithNewData.getLogin().equals(userWithOldData.getLogin()) + && usersByLogin.containsKey(userWithNewData.getLogin())) { log.error("Ошибка обновления: login {} уже используется", userWithNewData.getLogin()); throw new ValidationException("Этот логин уже используется"); } diff --git a/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java b/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java index daa3378..9c510ee 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/service/UserServiceTest.java @@ -62,7 +62,7 @@ void getCommonFriends() { userService.addFriend(user1.getId(), user3.getId()); userService.addFriend(user2.getId(), user3.getId()); - List commonFriends= userService.getCommonFriends(user1.getId(), user2.getId()); + List commonFriends = userService.getCommonFriends(user1.getId(), user2.getId()); assertTrue(commonFriends.contains(user3)); } From 030d8e9dfd28dbe19793401c8a7dbf516b37990c Mon Sep 17 00:00:00 2001 From: russuAV Date: Sat, 15 Mar 2025 21:24:10 +0500 Subject: [PATCH 5/5] 5 commit: - fix update methods in User Storage, Film Storage - add test for checking update methods --- .../storage/InMemoryFilmStorage.java | 31 ++++---- .../storage/InMemoryUserStorage.java | 58 +++++++++------ .../storage/InMemoryFilmStorageTest.java | 13 ++-- .../storage/InMemoryUserStorageTest.java | 72 ++++++++++++++++++- 4 files changed, 132 insertions(+), 42 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java index 1eb4bfe..a057377 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -8,6 +8,7 @@ import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; @Slf4j @@ -57,20 +58,26 @@ public Film update(Film filmWithNewData) { log.error("Ошибка обновления: фильм не найден"); throw new NotFoundException("Фильм не найден"); } - // меняем релиз-дату - if (filmWithNewData.isValidReleaseDate()) { - filmWithOldData.setReleaseDate(filmWithNewData.getReleaseDate()); - } - // меняем название - filmWithOldData.setName(filmWithNewData.getName()); - - //меняем описание - filmWithOldData.setDescription(filmWithNewData.getDescription()); - //меняем продолжительность фильма - filmWithOldData.setDuration(filmWithNewData.getDuration()); + Film updateFilm = new Film( + filmWithNewData.getId(), + filmWithNewData.getReleaseDate(), + filmWithNewData.getName(), + filmWithNewData.getDescription(), + filmWithNewData.getDuration() + ); + if (!updateFilm.isValidReleaseDate()) { + throw new ValidationException("Дата релиза должна быть не раньше 28 декабря 1895 года"); + } + if (filmWithNewData.getLikes() != null && !filmWithNewData.getLikes().isEmpty()) { + updateFilm.setLikes(new HashSet<>(filmWithNewData.getLikes())); + } else { + updateFilm.setLikes(filmWithOldData.getLikes()); + } + films.remove(filmWithOldData.getId(), filmWithOldData); + films.put(updateFilm.getId(), updateFilm); log.info("Данные о фильме '{}' успешно обновлены", filmWithOldData.getName()); - return filmWithOldData; + return updateFilm; } @Override diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index e0a0feb..2e39cfc 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -72,34 +72,50 @@ public User update(User userWithNewData) { log.error("Пользователь не найден"); throw new NotFoundException("Пользователь не найден"); } - if (!userWithNewData.getEmail().equals(userWithOldData.getEmail()) - && usersByEmail.containsKey(userWithNewData.getEmail())) { - log.error("Ошибка обновления: email {} уже используется", userWithNewData.getEmail()); - throw new ValidationException("Этот e-mail уже используется"); + // проверяем доступность email + if (!userWithNewData.getEmail().equals(userWithOldData.getEmail())) { + if (usersByEmail.containsKey(userWithNewData.getEmail())) { + User existingUserByEmail = usersByEmail.get(userWithNewData.getEmail()); + if (!existingUserByEmail.getId().equals(userWithNewData.getId())) { + log.error("Ошибка обновления: email {} уже используется", userWithNewData.getEmail()); + throw new ValidationException("Этот e-mail уже используется"); + } + } } - // обновляем e-mail - usersByEmail.remove(userWithOldData.getEmail()); - userWithOldData.setEmail(userWithNewData.getEmail()); - usersByEmail.put(userWithOldData.getEmail(), userWithOldData); + // проверяем доступность логина + if (!userWithNewData.getLogin().equals(userWithOldData.getLogin())) { + if (usersByLogin.containsKey(userWithNewData.getLogin())) { + User existingUserByLogin = usersByLogin.get(userWithNewData.getLogin()); + if (!existingUserByLogin.getId().equals(userWithNewData.getId())) { + log.error("Ошибка обновления: login {} уже используется", userWithNewData.getLogin()); + throw new ValidationException("Этот логин уже используется"); + } + } + } - // обновляем логин - if (!userWithNewData.getLogin().equals(userWithOldData.getLogin()) - && usersByLogin.containsKey(userWithNewData.getLogin())) { - log.error("Ошибка обновления: login {} уже используется", userWithNewData.getLogin()); - throw new ValidationException("Этот логин уже используется"); + User updateUser = new User( + userWithNewData.getId(), + userWithNewData.getEmail(), + userWithNewData.getLogin(), + userWithNewData.getName(), + userWithNewData.getBirthday() + ); + if (userWithNewData.getFriends() != null && !userWithNewData.getFriends().isEmpty()) { + updateUser.setFriends(new HashSet<>(userWithNewData.getFriends())); + } else { + updateUser.setFriends(userWithOldData.getFriends()); } + // удаляем старого пользователя и возвращаем нового + users.remove(userWithOldData.getId()); + usersByEmail.remove(userWithOldData.getEmail()); usersByLogin.remove(userWithOldData.getLogin()); - userWithOldData.setLogin(userWithNewData.getLogin()); - usersByLogin.put(userWithOldData.getLogin(), userWithOldData); - - // обновляем имя - userWithOldData.setName(userWithNewData.getName()); + users.put(userWithNewData.getId(), userWithNewData); + usersByLogin.put(userWithNewData.getLogin(), userWithNewData); + usersByEmail.put(userWithNewData.getEmail(), userWithNewData); - // обновляем дату рождения - userWithOldData.setBirthday(userWithNewData.getBirthday()); log.info("Пользователь с id {} успешно обновлён", userWithOldData.getId()); - return userWithOldData; + return updateUser; } @Override diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java index bcc1671..f475804 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorageTest.java @@ -66,14 +66,15 @@ void update() { "test1", "description1", 120); filmStorage.create(film1); - film1.setName("newTest1"); - film1.setDescription("newDescription1"); - film1.setDuration(130); - filmStorage.update(film1); + Film updateFilm1 = new Film(1L, LocalDate.of(1997, 1, 26), + "updateFilm1", "updateDescription1", 130); - assertEquals("newTest1", filmStorage.getFilmById(1L).getName()); - assertEquals("newDescription1", filmStorage.getFilmById(1L).getDescription()); + + filmStorage.update(updateFilm1); + + assertEquals("updateFilm1", filmStorage.getFilmById(1L).getName()); + assertEquals("updateDescription1", filmStorage.getFilmById(1L).getDescription()); assertEquals(130, filmStorage.getFilmById(1L).getDuration()); } } \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java index 7fc1192..81c5267 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorageTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; import java.time.LocalDate; @@ -65,13 +66,78 @@ void create() { void update() { User user1 = new User(1L, "user1@email.com", "user1", "user1", LocalDate.of(1997, 01, 26)); + User updateUser1 = new User(1L, "user1new@email.com", "newLogin1", "newUser1", + LocalDate.of(1997, 01, 26)); userStorage.create(user1); - user1.setName("newUser1"); - user1.setLogin("newLogin1"); - userStorage.update(user1); + userStorage.update(updateUser1); assertEquals("newUser1", userStorage.getUserById(user1.getId()).getName()); assertEquals("newLogin1", userStorage.getUserById(user1.getId()).getLogin()); } + + @Test + void createUserWithExistLogin() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + + User user2 = new User(2L, "user2@email.com", "user1", "user2", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + Exception exception = assertThrows(ValidationException.class, () -> { + userStorage.create(user2); + }); + assertEquals("Данный логин занят", exception.getMessage()); + } + + @Test + void createUserWithExistEmail() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user1@email.com", "user2", "user2", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + Exception exception = assertThrows(ValidationException.class, () -> { + userStorage.create(user2); + }); + assertEquals("Данный email уже используется", exception.getMessage()); + } + + @Test + void updateUserWithExistLogin() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 26)); + User updateUser1 = new User(1L, "user1new@email.com", "user2", "user1", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + userStorage.create(user2); + + Exception exception = assertThrows(ValidationException.class, () -> { + userStorage.update(updateUser1); + }); + assertEquals("Этот логин уже используется", exception.getMessage()); + } + + @Test + void updateUserWithExistEmail() { + User user1 = new User(1L, "user1@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + User user2 = new User(2L, "user2@email.com", "user2", "user2", + LocalDate.of(1997, 01, 26)); + User updateUser1 = new User(1L, "user2@email.com", "user1", "user1", + LocalDate.of(1997, 01, 26)); + + userStorage.create(user1); + userStorage.create(user2); + + Exception exception = assertThrows(ValidationException.class, () -> { + userStorage.update(updateUser1); + }); + assertEquals("Этот e-mail уже используется", exception.getMessage()); + } } \ No newline at end of file