Compare commits

...

3 Commits

6 changed files with 241 additions and 18 deletions
+5
View File
@@ -117,6 +117,11 @@
<version>${mockito.version}</version> <version>${mockito.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -0,0 +1,7 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.exception;
public class NotValidReviewException extends RuntimeException {
public NotValidReviewException(String message) {
super(message);
}
}
@@ -0,0 +1,52 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.validator;
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
import fr.iut_fbleau.but3.dev62.mylibrary.review.ReviewInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.NotValidReviewException;
import java.time.LocalDate;
public class ReviewValidator {
public static final String NOTE_CANNOT_BE_LOWER_THAN_1 = "Note is greater than or equal to 1";
public static final String NOTE_CANNOT_BE_UPPER_THAN_5 = "Note is less than or equal to 5";
public static final String COMMENT_CANNOT_BE_BLANK = "Comment cannot be blank";
public static final String PURCHASE_DATE_IS_NOT_VALID = "Date is not valid";
public ReviewValidator() {
}
public static void validate(ReviewInfo newReview) throws NotValidReviewException {
validateNoteLower1(newReview);
validateNoteUpper5(newReview);
validateComment(newReview);
validatePurchaseDate(newReview);
}
private static void validateNoteLower1(ReviewInfo newReview)
throws NotValidReviewException {
if (newReview.note() <= 1) {
throw new NotValidReviewException(NOTE_CANNOT_BE_LOWER_THAN_1);
}
}
private static void validateNoteUpper5(ReviewInfo newReview)
throws NotValidReviewException {
if (newReview.note() >= 5) {
throw new NotValidReviewException("Note is less than or equal to 5");
}
}
private static void validateComment(ReviewInfo newReview) throws NotValidReviewException {
if (newReview.comment().isBlank()) {
throw new NotValidReviewException(COMMENT_CANNOT_BE_BLANK);
}
}
private static void validatePurchaseDate(ReviewInfo newReview) throws NotValidReviewException {
if (newReview.purchaseDate().isAfter(LocalDate.now())) {
throw new NotValidReviewException(PURCHASE_DATE_IS_NOT_VALID);
}
}
}
@@ -24,8 +24,8 @@ public class ReviewConverterTest {
@DisplayName("Should convert ReviewInfo to Review domain object") @DisplayName("Should convert ReviewInfo to Review domain object")
void shouldConvertReviewInfoToDomain() { void shouldConvertReviewInfoToDomain() {
// Given // Given
LocalDate date = LocalDate.of(2026, 3, 24); LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo reviewInfo = new ReviewInfo(5, "tres bon livre", date); ReviewInfo reviewInfo = new ReviewInfo(5, "tres bon livre", purchaseDate);
// When // When
Review result = ReviewConverter.toDomain(reviewInfo); Review result = ReviewConverter.toDomain(reviewInfo);
@@ -45,13 +45,13 @@ public class ReviewConverterTest {
@Test @Test
@DisplayName("Should convert Review domain object to ReviewDTO with all fields mapped correctly") @DisplayName("Should convert Review domain object to ReviewDTO with all fields mapped correctly")
void shouldConvertReviewToDTO() { void shouldConvertReviewToDTO() {
LocalDate date = LocalDate.of(2026, 3, 24); LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
Review review = Review.builder() Review review = Review.builder()
.customerId(UUID.randomUUID()) .customerId(UUID.randomUUID())
.bookId(UUID.randomUUID()) .bookId(UUID.randomUUID())
.note(5) .note(5)
.comment("très bon livre") .comment("très bon livre")
.purchaseDate(date) .purchaseDate(purchaseDate)
.build(); .build();
ReviewDTO result = ReviewConverter.toDTO(review); ReviewDTO result = ReviewConverter.toDTO(review);
@@ -64,18 +64,4 @@ public class ReviewConverterTest {
assertEquals(review.getPurchaseDate(), result.getPurchaseDate()); assertEquals(review.getPurchaseDate(), result.getPurchaseDate());
} }
} }
@Test
@DisplayName("Should preserve empty string values during conversion")
void shouldPreserveEmptyStrings() {
LocalDate date = LocalDate.of(2026, 3, 24);
ReviewInfo reviewInfo = new ReviewInfo(5, "", date);
Review domainResult = ReviewConverter.toDomain(reviewInfo);
ReviewDTO dtoResult = ReviewConverter.toDTO(domainResult);
assertEquals(5, dtoResult.getNote());
assertEquals("", dtoResult.getComment());
assertEquals(date, dtoResult.getPurchaseDate());
}
} }
@@ -0,0 +1,60 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.exception;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class NotValidReviewExcpetionTest {
@Test
@DisplayName("Exception should be created with the provided message")
void testExceptionCreation() {
String errorMessage = "Review data is not valid";
NotValidReviewException exception = new NotValidReviewException(errorMessage);
assertEquals(errorMessage, exception.getMessage());
}
@ParameterizedTest
@ValueSource(strings = {
"Note is greater than or equal to 1",
"Note is less than or equal to 1",
"Comment cannot be empty"
})
@DisplayName("Exception should handle different validation messages")
void testExceptionWithDifferentMessages(String errorMessage) {
NotValidReviewException exception = new NotValidReviewException(errorMessage);
assertEquals(errorMessage, exception.getMessage());
}
@Test
@DisplayName("Exception should be properly thrown and caught")
void testExceptionCanBeThrownAndCaught() {
String errorMessage = "Comment field is empty";
Exception exception = assertThrows(NotValidReviewException.class, () -> {
throw new NotValidReviewException(errorMessage);
});
assertEquals(errorMessage, exception.getMessage());
}
@Test
@DisplayName("Exception should be catchable as a general Exception")
void testExceptionInheritance() {
String errorMessage = "Invalid review data";
try {
throw new NotValidReviewException(errorMessage);
} catch (Exception e) {
assertEquals(NotValidReviewException.class, e.getClass());
assertEquals(errorMessage, e.getMessage());
}
}
}
@@ -0,0 +1,113 @@
package fr.iut_fbleau.but3.dev62.mylibrary.review.validator;
import fr.iut_fbleau.but3.dev62.mylibrary.review.ReviewInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.NotValidReviewException;
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 static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ReviewValidatorTest {
@Test
@DisplayName("Should validate review with valid data")
void testValidateValidReview() {
LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo validReview = new ReviewInfo(3, "Bof", purchaseDate);
assertDoesNotThrow(() -> ReviewValidator.validate(validReview));
}
@Nested
@DisplayName("Note validation tests")
class NoteValidationTests {
@Test
@DisplayName("Should throw exception when note is lower than 1")
void testValidateNoteLower1() {
LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo reviewWithNoteLower1 = new ReviewInfo(0, "Bof", purchaseDate);
NotValidReviewException exception = assertThrows(
NotValidReviewException.class,
() -> ReviewValidator.validate(reviewWithNoteLower1)
);
assertEquals(ReviewValidator.NOTE_CANNOT_BE_LOWER_THAN_1, exception.getMessage());
}
@Test
@DisplayName("Should throw exception when note is upper than 5")
void testValidateNoteUpper5() {
LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo reviewWithNoteUpper5 = new ReviewInfo(6, "Bof", purchaseDate);
NotValidReviewException exception = assertThrows(
NotValidReviewException.class,
() -> ReviewValidator.validate(reviewWithNoteUpper5)
);
assertEquals(ReviewValidator.NOTE_CANNOT_BE_UPPER_THAN_5, exception.getMessage());
}
}
@Nested
@DisplayName("Comment validation tests")
class CommentValidationTests {
@Test
@DisplayName("Should throw exception when comment is blank")
void testValidateBlankComment() {
LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo reviewWithBlankComment = new ReviewInfo(3, "", purchaseDate);
NotValidReviewException exception = assertThrows(
NotValidReviewException.class,
() -> ReviewValidator.validate(reviewWithBlankComment)
);
assertEquals(ReviewValidator.COMMENT_CANNOT_BE_BLANK, exception.getMessage());
}
@ParameterizedTest
@ValueSource(strings = {" ", " ", "\t", "\n"})
@DisplayName("Should throw exception when last name contains only whitespace")
void testValidateWhitespaceLastName(String whitespace) {
LocalDate purchaseDate = LocalDate.of(2026, 3, 24);
ReviewInfo reviewWithBlankComment = new ReviewInfo(3, whitespace, purchaseDate);
NotValidReviewException exception = assertThrows(
NotValidReviewException.class,
() -> ReviewValidator.validate(reviewWithBlankComment)
);
assertEquals(ReviewValidator.COMMENT_CANNOT_BE_BLANK, exception.getMessage());
}
}
@Nested
@DisplayName("Purchase date validation tests")
class PurchaseDateValidationTests {
@Test
@DisplayName("Should throw exception when purchase date is after the actual date")
void testValidateFuturPurchaseDate() {
LocalDate futurepurchaseDate = LocalDate.of(2026, 6, 24);
ReviewInfo reviewWithFuturPurchaseDate = new ReviewInfo(2, "Bof", futurepurchaseDate);
NotValidReviewException exception = assertThrows(
NotValidReviewException.class,
() -> ReviewValidator.validate(reviewWithFuturPurchaseDate)
);
assertEquals(ReviewValidator.PURCHASE_DATE_IS_NOT_VALID, exception.getMessage());
}
}
}