diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/repository/AvisRepositoryTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/repository/AvisRepositoryTest.java new file mode 100644 index 0000000..3cda2be --- /dev/null +++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/repository/AvisRepositoryTest.java @@ -0,0 +1,184 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.avis.repository; + +import fr.iut_fbleau.but3.dev62.mylibrary.avis.entity.Avis; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class AvisRepositoryTest { + + private AvisRepository repository; + private Avis avis1; + private Avis avis2; + private UUID clientId1; + private UUID livreId1; + + @BeforeEach + void setUp() { + repository = new AvisRepository(); + clientId1 = UUID.randomUUID(); + livreId1 = UUID.randomUUID(); + + avis1 = Avis.builder() + .clientId(clientId1) + .livreId(livreId1) + .note(5) + .commentaire("Excellent livre !") + .dateAchat(LocalDate.of(2024, 1, 15)) + .build(); + avis1.setRandomUUID(); + + avis2 = Avis.builder() + .clientId(UUID.randomUUID()) + .livreId(livreId1) + .note(3) + .commentaire("Pas mal") + .dateAchat(LocalDate.of(2024, 2, 10)) + .build(); + avis2.setRandomUUID(); + } + + @Test + @DisplayName("New repository should be empty") + void testNewRepositoryIsEmpty() { + assertTrue(repository.findAll().isEmpty()); + } + + @Nested + @DisplayName("Save operations") + class SaveOperations { + + @Test + @DisplayName("Save should add a new avis") + void testSaveNewAvis() { + Avis saved = repository.save(avis1); + + assertEquals(1, repository.findAll().size()); + assertEquals(avis1.getId(), saved.getId()); + } + + @Test + @DisplayName("Save should update existing avis with same ID") + void testSaveUpdatesExistingAvis() { + repository.save(avis1); + UUID id = avis1.getId(); + + Avis updated = Avis.builder() + .id(id) + .clientId(clientId1) + .livreId(livreId1) + .note(3) + .commentaire("Finalement moyen") + .dateAchat(LocalDate.of(2024, 1, 15)) + .build(); + + Avis saved = repository.save(updated); + + assertEquals(1, repository.findAll().size()); + assertEquals(id, saved.getId()); + assertEquals(3, saved.getNote()); + } + + @Test + @DisplayName("Save multiple avis should add all of them") + void testSaveMultipleAvis() { + repository.save(avis1); + repository.save(avis2); + + assertEquals(2, repository.findAll().size()); + } + } + + @Nested + @DisplayName("Find operations") + class FindOperations { + + @BeforeEach + void setUpAvis() { + repository.save(avis1); + repository.save(avis2); + } + + @Test + @DisplayName("FindById should return avis with matching ID") + void testFindById() { + Optional found = repository.findById(avis1.getId()); + + assertTrue(found.isPresent()); + assertEquals(avis1.getId(), found.get().getId()); + } + + @Test + @DisplayName("FindById should return empty Optional when ID doesn't exist") + void testFindByIdNotFound() { + Optional found = repository.findById(UUID.randomUUID()); + + assertTrue(found.isEmpty()); + } + + @Test + @DisplayName("FindByLivreId should return all avis for a book") + void testFindByLivreId() { + List found = repository.findByLivreId(livreId1); + + assertEquals(2, found.size()); + } + + @Test + @DisplayName("FindByClientId should return all avis for a client") + void testFindByClientId() { + List found = repository.findByClientId(clientId1); + + assertEquals(1, found.size()); + assertEquals(avis1.getId(), found.getFirst().getId()); + } + + @Test + @DisplayName("ExistsById should return true when ID exists") + void testExistsByIdExists() { + assertTrue(repository.existsById(avis1.getId())); + } + + @Test + @DisplayName("ExistsById should return false when ID doesn't exist") + void testExistsByIdNotExists() { + assertFalse(repository.existsById(UUID.randomUUID())); + } + } + + @Nested + @DisplayName("Delete operations") + class DeleteOperations { + + @BeforeEach + void setUpAvis() { + repository.save(avis1); + repository.save(avis2); + } + + @Test + @DisplayName("Delete should remove the specified avis") + void testDelete() { + repository.delete(avis1); + + assertEquals(1, repository.findAll().size()); + assertFalse(repository.findAll().contains(avis1)); + } + + @Test + @DisplayName("DeleteAll should remove all avis") + void testDeleteAll() { + repository.deleteAll(); + + assertTrue(repository.findAll().isEmpty()); + } + } +} \ No newline at end of file diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/validator/AvisValidatorTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/validator/AvisValidatorTest.java new file mode 100644 index 0000000..3fee128 --- /dev/null +++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/avis/validator/AvisValidatorTest.java @@ -0,0 +1,131 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.avis.validator; + +import fr.iut_fbleau.but3.dev62.mylibrary.avis.AvisInfo; +import fr.iut_fbleau.but3.dev62.mylibrary.avis.exception.NotValidAvisException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.time.LocalDate; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class AvisValidatorTest { + + private final UUID clientId = UUID.randomUUID(); + private final UUID livreId = UUID.randomUUID(); + + private AvisInfo validAvis() { + return new AvisInfo(clientId, livreId, 5, "Excellent livre !", LocalDate.of(2024, 1, 15)); + } + + @Test + @DisplayName("Should validate avis with valid data") + void testValidateValidAvis() { + assertDoesNotThrow(() -> AvisValidator.validate(validAvis())); + } + + @Nested + @DisplayName("ClientId validation tests") + class ClientIdValidationTests { + + @Test + @DisplayName("Should throw exception when clientId is null") + void testValidateNullClientId() { + AvisInfo avis = new AvisInfo(null, livreId, 5, "Commentaire", LocalDate.now()); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.CLIENT_ID_CANNOT_BE_NULL, exception.getMessage()); + } + } + + @Nested + @DisplayName("LivreId validation tests") + class LivreIdValidationTests { + + @Test + @DisplayName("Should throw exception when livreId is null") + void testValidateNullLivreId() { + AvisInfo avis = new AvisInfo(clientId, null, 5, "Commentaire", LocalDate.now()); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.LIVRE_ID_CANNOT_BE_NULL, exception.getMessage()); + } + } + + @Nested + @DisplayName("Note validation tests") + class NoteValidationTests { + + @ParameterizedTest + @ValueSource(ints = {1, 2, 3, 4, 5}) + @DisplayName("Should validate when note is between 1 and 5") + void testValidateValidNote(int validNote) { + AvisInfo avis = new AvisInfo(clientId, livreId, validNote, "Commentaire", LocalDate.now()); + assertDoesNotThrow(() -> AvisValidator.validate(avis)); + } + + @ParameterizedTest + @ValueSource(ints = {0, -1, 6, 10}) + @DisplayName("Should throw exception when note is out of range") + void testValidateInvalidNote(int invalidNote) { + AvisInfo avis = new AvisInfo(clientId, livreId, invalidNote, "Commentaire", LocalDate.now()); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.NOTE_MUST_BE_BETWEEN_1_AND_5, exception.getMessage()); + } + } + + @Nested + @DisplayName("Commentaire validation tests") + class CommentaireValidationTests { + + @Test + @DisplayName("Should throw exception when commentaire is blank") + void testValidateBlankCommentaire() { + AvisInfo avis = new AvisInfo(clientId, livreId, 5, "", LocalDate.now()); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.COMMENTAIRE_CANNOT_BE_BLANK, exception.getMessage()); + } + + @ParameterizedTest + @ValueSource(strings = {" ", " ", "\t", "\n"}) + @DisplayName("Should throw exception when commentaire contains only whitespace") + void testValidateWhitespaceCommentaire(String whitespace) { + AvisInfo avis = new AvisInfo(clientId, livreId, 5, whitespace, LocalDate.now()); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.COMMENTAIRE_CANNOT_BE_BLANK, exception.getMessage()); + } + } + + @Nested + @DisplayName("DateAchat validation tests") + class DateAchatValidationTests { + + @Test + @DisplayName("Should throw exception when dateAchat is null") + void testValidateNullDateAchat() { + AvisInfo avis = new AvisInfo(clientId, livreId, 5, "Commentaire", null); + + NotValidAvisException exception = assertThrows(NotValidAvisException.class, + () -> AvisValidator.validate(avis)); + + assertEquals(AvisValidator.DATE_ACHAT_CANNOT_BE_NULL, exception.getMessage()); + } + } +} \ No newline at end of file