forked from pierront/mylibrary-template
Books
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Getter
|
||||||
|
public class BookDTO {
|
||||||
|
private final String isbn;
|
||||||
|
private final String titre;
|
||||||
|
private final String auteur;
|
||||||
|
private final String editeur;
|
||||||
|
private final Date date;
|
||||||
|
private final int prix; //decimal(positive)
|
||||||
|
private final int stockInitial; //integer(min:0)
|
||||||
|
private final String[] categories;
|
||||||
|
private final String description;
|
||||||
|
private final String langue;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book;
|
||||||
|
|
||||||
|
public record BookInfo(String isbn, String titre, String auteur, String editeur) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.converter;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public final class BookConverter {
|
||||||
|
private BookConverter(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Book toDomain(BookInfo newBook) {
|
||||||
|
return Book.builder()
|
||||||
|
.isbn(newBook.isbn())
|
||||||
|
.titre(newBook.titre())
|
||||||
|
.auteur(newBook.auteur())
|
||||||
|
.editeur(newBook.editeur())
|
||||||
|
.date(new Date(System.currentTimeMillis()))
|
||||||
|
.prix(0)
|
||||||
|
.stockInitial(0)
|
||||||
|
.categories(new String[]{})
|
||||||
|
.description("")
|
||||||
|
.langue("")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BookDTO toDTO(Book book) {
|
||||||
|
return BookDTO.builder()
|
||||||
|
.isbn(book.getIsbn())
|
||||||
|
.titre(book.getTitre())
|
||||||
|
.auteur(book.getAuteur())
|
||||||
|
.editeur(book.getEditeur())
|
||||||
|
.date(book.getDate())
|
||||||
|
.prix(book.getPrix())
|
||||||
|
.stockInitial(book.getStockInitial())
|
||||||
|
.categories(book.getCategories())
|
||||||
|
.description(book.getDescription())
|
||||||
|
.langue(book.getLangue())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.entity;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.IllegalBookQuantityException;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Getter
|
||||||
|
public class Book {
|
||||||
|
private String isbn;
|
||||||
|
private String titre;
|
||||||
|
private String auteur;
|
||||||
|
private String editeur;
|
||||||
|
private Date date;
|
||||||
|
private int prix; //decimal(positive)
|
||||||
|
private int stockInitial; //integer(min:0)
|
||||||
|
private String[] categories;
|
||||||
|
private String description;
|
||||||
|
private String langue;
|
||||||
|
|
||||||
|
public void increaseQuantity(int number){
|
||||||
|
this.stockInitial+=number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decreaseQuantity(int number) throws IllegalBookQuantityException {
|
||||||
|
if (stockInitial<number) throw new IllegalBookQuantityException(stockInitial,number);
|
||||||
|
this.stockInitial-=number;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class BookNotFoundException extends Exception {
|
||||||
|
public static final String THE_BOOK_WITH_ISBN_DOES_NOT_EXIST_MESSAGE = "The book with id {0} does not exist";
|
||||||
|
|
||||||
|
public BookNotFoundException(String isbn) {
|
||||||
|
super(MessageFormat.format(THE_BOOK_WITH_ISBN_DOES_NOT_EXIST_MESSAGE, isbn));
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
public class IllegalBookQuantityException extends Exception {
|
||||||
|
|
||||||
|
public static final String CANNOT_SET_A_NEGATIVE_QUANTITY= "Cannot remove {0} points from {1} points";
|
||||||
|
|
||||||
|
public IllegalBookQuantityException(int initialQuantity, int addedQuantity) {
|
||||||
|
super(MessageFormat.format(CANNOT_SET_A_NEGATIVE_QUANTITY, initialQuantity, addedQuantity));
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
|
||||||
|
|
||||||
|
public class NotValidBookException extends Exception {
|
||||||
|
public NotValidBookException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.repository;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public final class BookRepository {
|
||||||
|
|
||||||
|
private final List<Book> books = new ArrayList<>();
|
||||||
|
|
||||||
|
public List<Book> findAll() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAll() {
|
||||||
|
books.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Book save(Book newBook){
|
||||||
|
Optional<Book> optionalBookWithSameIsbn = this.findByIsbn(newBook.getIsbn());
|
||||||
|
optionalBookWithSameIsbn.ifPresent(books::remove);
|
||||||
|
this.books.add(newBook);
|
||||||
|
|
||||||
|
return newBook;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Book> findByIsbn(String isbn) {
|
||||||
|
return this.books.stream()
|
||||||
|
.filter(book -> book.getIsbn().equals(isbn))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existsByIsbn(String isbn){
|
||||||
|
return this.books.stream()
|
||||||
|
.anyMatch(book -> book.getIsbn().equals(isbn));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Book> findByCategorie(String categorie) {
|
||||||
|
return this.books.stream()
|
||||||
|
.filter(book -> Arrays.asList(book.getCategories()).contains(categorie))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Book> findByLangue(String langue) {
|
||||||
|
return this.books.stream()
|
||||||
|
.filter(book -> book.getLangue().equals(langue))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(Book book) {this.books.remove(book);}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.usecase;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.converter.BookConverter;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.IllegalBookQuantityException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.validator.BookValidator;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class BookUseCase {
|
||||||
|
private final BookRepository bookRepository;
|
||||||
|
|
||||||
|
public BookUseCase(BookRepository bookRepository) {
|
||||||
|
this.bookRepository = bookRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String registerBook(BookInfo newBook) throws NotValidBookException {
|
||||||
|
BookValidator.validate(newBook);
|
||||||
|
Book bookToRegister = BookConverter.toDomain(newBook);
|
||||||
|
Book bookToRegistered = bookRepository.save(bookToRegister);
|
||||||
|
return bookToRegistered.getIsbn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<BookDTO> findBookByCategorie(String categorie) {
|
||||||
|
Optional<Book> optionalBook = bookRepository.findByCategorie(categorie);
|
||||||
|
return optionalBook.map(BookConverter::toDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BookDTO updateBook(String isbn, BookInfo bookInfo)
|
||||||
|
throws BookNotFoundException, NotValidBookException {
|
||||||
|
BookValidator.validate(bookInfo);
|
||||||
|
Book bookByISBN = getBookIfDoesNotExistThrowBookNotFoundException(
|
||||||
|
isbn);
|
||||||
|
Book book = Book.builder()
|
||||||
|
.isbn(isbn)
|
||||||
|
.titre(bookInfo.titre())
|
||||||
|
.auteur(bookInfo.auteur())
|
||||||
|
.editeur(bookInfo.editeur())
|
||||||
|
.date(bookByISBN.getDate())
|
||||||
|
.prix(bookByISBN.getPrix())
|
||||||
|
.stockInitial(bookByISBN.getStockInitial())
|
||||||
|
.categories(bookByISBN.getCategories())
|
||||||
|
.description(bookByISBN.getDescription())
|
||||||
|
.langue(bookByISBN.getLangue())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Book updatedBook = bookRepository.save(book);
|
||||||
|
|
||||||
|
return BookConverter.toDTO(updatedBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteBook(String isbn) throws BookNotFoundException {
|
||||||
|
Book bookToDelete = getBookIfDoesNotExistThrowBookNotFoundException(isbn);
|
||||||
|
this.bookRepository.delete(bookToDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int addQuantity(String isbn, int loyaltyPointToAdd) throws BookNotFoundException {
|
||||||
|
Book bookToAddQuantity = getBookIfDoesNotExistThrowBookNotFoundException(isbn);
|
||||||
|
bookToAddQuantity.increaseQuantity(loyaltyPointToAdd);
|
||||||
|
bookRepository.save(bookToAddQuantity);
|
||||||
|
return bookToAddQuantity.getStockInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int subtractQuantity(String isbn, int loyaltyPointToRemove)
|
||||||
|
throws BookNotFoundException, IllegalBookQuantityException {
|
||||||
|
Book bookToSubtractQuantity = getBookIfDoesNotExistThrowBookNotFoundException(
|
||||||
|
isbn);
|
||||||
|
bookToSubtractQuantity.decreaseQuantity(loyaltyPointToRemove);
|
||||||
|
bookRepository.save(bookToSubtractQuantity);
|
||||||
|
return bookToSubtractQuantity.getStockInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Book getBookIfDoesNotExistThrowBookNotFoundException(String isbn)
|
||||||
|
throws BookNotFoundException {
|
||||||
|
Optional<Book> optionalBookById = bookRepository.findByIsbn(isbn);
|
||||||
|
if (optionalBookById.isEmpty()) {
|
||||||
|
throw new BookNotFoundException(isbn);
|
||||||
|
}
|
||||||
|
return optionalBookById.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.validator;
|
||||||
|
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
|
||||||
|
|
||||||
|
public class BookValidator {
|
||||||
|
|
||||||
|
public static final String ISBN_IS_NOT_VALID = "ISBN is not valid";
|
||||||
|
public static final String TITRE_CANNOT_BE_BLANK = "Titre cannot be blank";
|
||||||
|
public static final String AUTEUR_CANNOT_BE_BLANK = "Auteur cannot be blank";
|
||||||
|
public static final String EDITEUR_CANNOT_BE_BLANK = "Editeur cannot be blank";
|
||||||
|
public static final String ISBN_NUMBER_REGEX = "\\d{13}";
|
||||||
|
|
||||||
|
private BookValidator() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validate(BookInfo newBook) throws NotValidBookException {
|
||||||
|
validateIsbn(newBook);
|
||||||
|
validateTitre(newBook);
|
||||||
|
validateAuteur(newBook);
|
||||||
|
validateEditeur(newBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateIsbn(BookInfo newBook)
|
||||||
|
throws NotValidBookException {
|
||||||
|
if (newBook.isbn().length() != 13) {
|
||||||
|
throw new NotValidBookException(ISBN_IS_NOT_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateTitre(BookInfo newBook)
|
||||||
|
throws NotValidBookException {
|
||||||
|
if (newBook.titre().isBlank()) {
|
||||||
|
throw new NotValidBookException(TITRE_CANNOT_BE_BLANK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateAuteur(BookInfo newBook) throws NotValidBookException {
|
||||||
|
if (newBook.auteur().isBlank()) {
|
||||||
|
throw new NotValidBookException(AUTEUR_CANNOT_BE_BLANK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateEditeur(BookInfo newBook) throws NotValidBookException {
|
||||||
|
if (newBook.editeur().isBlank()) {
|
||||||
|
throw new NotValidBookException(EDITEUR_CANNOT_BE_BLANK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.converter;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
@DisplayName("BookConverter Unit Tests")
|
||||||
|
public class BookConverterTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("toDomain() method tests")
|
||||||
|
class ToDomainTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should convert BookInfo to Book domain object with loyalty points initialized to 0")
|
||||||
|
void shouldConvertBookInfoToDomain() {
|
||||||
|
// Given
|
||||||
|
BookInfo bookInfo = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo","Glénat");
|
||||||
|
|
||||||
|
// When
|
||||||
|
Book result = BookConverter.toDomain(bookInfo);
|
||||||
|
|
||||||
|
// Then
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(bookInfo.isbn(), result.getIsbn());
|
||||||
|
assertEquals(bookInfo.titre(), result.getTitre());
|
||||||
|
assertEquals(bookInfo.auteur(), result.getAuteur());
|
||||||
|
assertEquals(bookInfo.editeur(), result.getEditeur());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("toDTO() method tests")
|
||||||
|
class ToDTOTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should convert Book domain object to BookDTO with all fields mapped correctly")
|
||||||
|
void shouldConvertBookToDTO() {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.isbn("9782344067949")
|
||||||
|
.titre("Ruri Dragon")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
BookDTO result = BookConverter.toDTO(customer);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(customer.getIsbn(), result.getIsbn());
|
||||||
|
assertEquals(customer.getTitre(), result.getTitre());
|
||||||
|
assertEquals(customer.getAuteur(), result.getAuteur());
|
||||||
|
assertEquals(customer.getEditeur(), result.getEditeur());
|
||||||
|
assertEquals(customer.getPrix(), result.getPrix());
|
||||||
|
assertEquals(customer.getStockInitial(), result.getStockInitial());
|
||||||
|
assertEquals(customer.getCategories(), result.getCategories());
|
||||||
|
assertEquals(customer.getLangue(), result.getLangue());
|
||||||
|
assertEquals(customer.getDescription(), result.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should handle null values properly when converting between objects")
|
||||||
|
void shouldHandleNullValuesGracefully() {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.isbn("9782344067949")
|
||||||
|
.titre(null)
|
||||||
|
.auteur("NullTest")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(null)
|
||||||
|
.langue(null)
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
BookDTO result = BookConverter.toDTO(customer);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertNull(result.getTitre());
|
||||||
|
assertEquals("NullTest", result.getAuteur());
|
||||||
|
assertNull(result.getCategories());
|
||||||
|
assertNull(result.getLangue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should preserve empty string values during conversion")
|
||||||
|
void shouldPreserveEmptyStrings() {
|
||||||
|
BookInfo bookInfo = new BookInfo("", "", "","");
|
||||||
|
|
||||||
|
Book domainResult = BookConverter.toDomain(bookInfo);
|
||||||
|
BookDTO dtoResult = BookConverter.toDTO(domainResult);
|
||||||
|
|
||||||
|
assertEquals("", dtoResult.getIsbn());
|
||||||
|
assertEquals("", dtoResult.getTitre());
|
||||||
|
assertEquals("", dtoResult.getAuteur());
|
||||||
|
assertEquals("", dtoResult.getEditeur());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.entity;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.IllegalBookQuantityException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
class BookTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Builder should create a valid Book instance")
|
||||||
|
void testBookBuilder() {
|
||||||
|
String isbn = "9782344067949";
|
||||||
|
String titre = "Ruri Dragon";
|
||||||
|
String auteur = "Masaoki Shindo";
|
||||||
|
String editeur = "Glénat";
|
||||||
|
Date date = new Date(System.currentTimeMillis());
|
||||||
|
int prix = 10; //decimal(positive)
|
||||||
|
int stockInitial = 20; //integer(min:0)
|
||||||
|
String[] categories = new String[]{"Manga","Shonen"};
|
||||||
|
String description = "Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !";
|
||||||
|
String langue = "fr";
|
||||||
|
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.isbn(isbn)
|
||||||
|
.titre(titre)
|
||||||
|
.auteur(auteur)
|
||||||
|
.editeur(editeur)
|
||||||
|
.prix(prix)
|
||||||
|
.stockInitial(stockInitial)
|
||||||
|
.categories(categories)
|
||||||
|
.langue(langue)
|
||||||
|
.description(description)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals(isbn, customer.getIsbn());
|
||||||
|
assertEquals(titre, customer.getTitre());
|
||||||
|
assertEquals(auteur, customer.getAuteur());
|
||||||
|
assertEquals(editeur, customer.getEditeur());
|
||||||
|
assertEquals(prix, customer.getPrix());
|
||||||
|
assertEquals(stockInitial, customer.getStockInitial());
|
||||||
|
assertEquals(categories, customer.getCategories());
|
||||||
|
assertEquals(langue, customer.getLangue());
|
||||||
|
assertEquals(description, customer.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Quantity Tests")
|
||||||
|
class QuantityTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("increaseQuantity should correctly increment loyalty points")
|
||||||
|
void testincreaseQuantity() {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
int quantityToAdd = 25;
|
||||||
|
int expectedQuantity = 75;
|
||||||
|
|
||||||
|
customer.increaseQuantity(quantityToAdd);
|
||||||
|
|
||||||
|
assertEquals(expectedQuantity, customer.getStockInitial());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("increaseQuantity should handle zero points correctly")
|
||||||
|
void testAddZeroQuantity() {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
customer.increaseQuantity(0);
|
||||||
|
|
||||||
|
assertEquals(50, customer.getStockInitial());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("decreaseQuantity should correctly decrement loyalty points")
|
||||||
|
void testDecreaseQuantity() throws IllegalBookQuantityException {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
int quantityToRemove = 20;
|
||||||
|
int expectedQuantity = 30;
|
||||||
|
|
||||||
|
customer.decreaseQuantity(quantityToRemove);
|
||||||
|
|
||||||
|
assertEquals(expectedQuantity, customer.getStockInitial());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("removeQuantity should handle removing exactly all points")
|
||||||
|
void testRemoveAllQuantity() throws IllegalBookQuantityException {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
customer.decreaseQuantity(50);
|
||||||
|
|
||||||
|
assertEquals(0, customer.getStockInitial());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("removeQuantity should throw exception when trying to remove more points than available")
|
||||||
|
void testRemoveTooManyQuantity() {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
int quantityToRemove = 75;
|
||||||
|
|
||||||
|
IllegalBookQuantityException exception = assertThrows(
|
||||||
|
IllegalBookQuantityException.class,
|
||||||
|
() -> customer.decreaseQuantity(quantityToRemove)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(50, customer.getStockInitial());
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains(String.valueOf(quantityToRemove)));
|
||||||
|
assertTrue(exception.getMessage().contains(String.valueOf(customer.getStockInitial())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("removeQuantity should handle removing zero points correctly")
|
||||||
|
void testRemoveZeroQuantity() throws IllegalBookQuantityException {
|
||||||
|
Book customer = Book.builder()
|
||||||
|
.stockInitial(50)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
customer.decreaseQuantity(0);
|
||||||
|
|
||||||
|
assertEquals(50, customer.getStockInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class BookNotFoundExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception message should contain the UUID provided")
|
||||||
|
void testExceptionMessageContainsUUID() {
|
||||||
|
String isbn = "9782344067949";
|
||||||
|
|
||||||
|
BookNotFoundException exception = new BookNotFoundException(isbn);
|
||||||
|
|
||||||
|
String expectedMessage = String.format("The book with id %s does not exist", isbn);
|
||||||
|
assertEquals(expectedMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should use the correct constant message format")
|
||||||
|
void testExceptionUsesConstantMessageFormat() {
|
||||||
|
String isbn = "9782344067949";
|
||||||
|
|
||||||
|
BookNotFoundException exception = new BookNotFoundException(isbn);
|
||||||
|
|
||||||
|
String expectedFormatWithPlaceholder = "The book with id {0} does not exist";
|
||||||
|
assertEquals(BookNotFoundException.THE_BOOK_WITH_ISBN_DOES_NOT_EXIST_MESSAGE,
|
||||||
|
expectedFormatWithPlaceholder);
|
||||||
|
assertTrue(exception.getMessage().contains(isbn));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should be properly thrown and caught")
|
||||||
|
void testExceptionCanBeThrownAndCaught() {
|
||||||
|
String isbn = "9782344067949";
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new BookNotFoundException(isbn);
|
||||||
|
} catch (BookNotFoundException e) {
|
||||||
|
String expectedMessage = String.format("The book with id %s does not exist", isbn);
|
||||||
|
assertEquals(expectedMessage, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.exception;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class IllegalBookQuantityExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception message should contain the needed and actual points")
|
||||||
|
void testExceptionMessageContainsPoints() {
|
||||||
|
int neededPoints = 100;
|
||||||
|
int actualPoints = 50;
|
||||||
|
|
||||||
|
IllegalBookQuantityException exception = new IllegalBookQuantityException(neededPoints, actualPoints);
|
||||||
|
|
||||||
|
String expectedMessage = "Cannot remove 100 points from 50 points";
|
||||||
|
assertEquals(expectedMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"100, 50",
|
||||||
|
"75, 25",
|
||||||
|
"200, 150",
|
||||||
|
"1000, 750"
|
||||||
|
})
|
||||||
|
@DisplayName("Exception message should be formatted correctly for different point values")
|
||||||
|
void testExceptionMessageForDifferentPointValues(int neededPoints, int actualPoints) {
|
||||||
|
IllegalBookQuantityException exception = new IllegalBookQuantityException(neededPoints, actualPoints);
|
||||||
|
|
||||||
|
String expectedMessage = MessageFormat.format(IllegalBookQuantityException.CANNOT_SET_A_NEGATIVE_QUANTITY, neededPoints, actualPoints);
|
||||||
|
assertEquals(expectedMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should use the correct constant message format")
|
||||||
|
void testExceptionUsesConstantMessageFormat() {
|
||||||
|
int neededPoints = 100;
|
||||||
|
int actualPoints = 50;
|
||||||
|
|
||||||
|
IllegalBookQuantityException exception = new IllegalBookQuantityException(neededPoints, actualPoints);
|
||||||
|
|
||||||
|
String expectedFormatWithPlaceholder = "Cannot remove {0} points from {1} points";
|
||||||
|
assertEquals(IllegalBookQuantityException.CANNOT_SET_A_NEGATIVE_QUANTITY,
|
||||||
|
expectedFormatWithPlaceholder);
|
||||||
|
assertTrue(exception.getMessage().contains(String.valueOf(neededPoints)));
|
||||||
|
assertTrue(exception.getMessage().contains(String.valueOf(actualPoints)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should be properly thrown and caught")
|
||||||
|
void testExceptionCanBeThrownAndCaught() {
|
||||||
|
int neededPoints = 100;
|
||||||
|
int actualPoints = 50;
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new IllegalBookQuantityException(neededPoints, actualPoints);
|
||||||
|
} catch (IllegalBookQuantityException e) {
|
||||||
|
String expectedMessage = String.format("Cannot remove %d points from %d points", neededPoints, actualPoints);
|
||||||
|
assertEquals(expectedMessage, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.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;
|
||||||
|
|
||||||
|
class NotValidBookExceptionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should be created with the provided message")
|
||||||
|
void testExceptionCreation() {
|
||||||
|
String errorMessage = "Customer data is not valid";
|
||||||
|
|
||||||
|
NotValidBookException exception = new NotValidBookException(errorMessage);
|
||||||
|
|
||||||
|
assertEquals(errorMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {
|
||||||
|
"ISBN is required",
|
||||||
|
"Title is required",
|
||||||
|
"Auteur is required",
|
||||||
|
"Editeur is required"
|
||||||
|
})
|
||||||
|
@DisplayName("Exception should handle different validation messages")
|
||||||
|
void testExceptionWithDifferentMessages(String errorMessage) {
|
||||||
|
NotValidBookException exception = new NotValidBookException(errorMessage);
|
||||||
|
|
||||||
|
assertEquals(errorMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should be properly thrown and caught")
|
||||||
|
void testExceptionCanBeThrownAndCaught() {
|
||||||
|
String errorMessage = "Required field is missing";
|
||||||
|
|
||||||
|
Exception exception = assertThrows(NotValidBookException.class, () -> {
|
||||||
|
throw new NotValidBookException(errorMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(errorMessage, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Exception should be catchable as a general Exception")
|
||||||
|
void testExceptionInheritance() {
|
||||||
|
String errorMessage = "Invalid customer data";
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new NotValidBookException(errorMessage);
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertEquals(NotValidBookException.class, e.getClass());
|
||||||
|
assertEquals(errorMessage, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+240
@@ -0,0 +1,240 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.repository;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
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.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BookRepositoryTest {
|
||||||
|
|
||||||
|
private BookRepository repository;
|
||||||
|
private Book book1;
|
||||||
|
private Book book2;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
repository = new BookRepository();
|
||||||
|
|
||||||
|
book1 = Book.builder()
|
||||||
|
.isbn("9782344067949")
|
||||||
|
.titre("Ruri Dragon")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
book2 = Book.builder()
|
||||||
|
.isbn("9782344070214")
|
||||||
|
.titre("Ruri Dragon 2")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri a balancé une décharge électrique en plein cours et découvert ainsi un nouvel attribut de dragon ! Elle s’exerce tant bien que mal pour contrôler ces nouvelles habiletés. \nMais alors qu’elle s’habitue petit à petit à son environnement scolaire, elle apprend qu’une camarade de classe l’évite sciemment !")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("New repository should be empty")
|
||||||
|
void testNewRepositoryIsEmpty() {
|
||||||
|
List<Book> books = repository.findAll();
|
||||||
|
|
||||||
|
assertTrue(books.isEmpty());
|
||||||
|
assertEquals(0, books.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Save operations")
|
||||||
|
class SaveOperations {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Save should add a new book")
|
||||||
|
void testSaveNewBook() {
|
||||||
|
Book savedBook = repository.save(book1);
|
||||||
|
|
||||||
|
assertEquals(1, repository.findAll().size());
|
||||||
|
assertEquals(book1.getIsbn(), savedBook.getIsbn());
|
||||||
|
assertEquals(book1.getTitre(), savedBook.getTitre());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Save should update existing book with same ID")
|
||||||
|
void testSaveUpdatesExistingBook() {
|
||||||
|
repository.save(book1);
|
||||||
|
|
||||||
|
String isbn = book1.getIsbn();
|
||||||
|
Book updatedBook = Book.builder()
|
||||||
|
.isbn(isbn)
|
||||||
|
.titre("Updated")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(150)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Book savedBook = repository.save(updatedBook);
|
||||||
|
|
||||||
|
assertEquals(1, repository.findAll().size());
|
||||||
|
assertEquals(isbn, savedBook.getIsbn());
|
||||||
|
assertEquals("Updated", savedBook.getTitre());
|
||||||
|
assertEquals("Glénat", savedBook.getEditeur());
|
||||||
|
assertEquals(150, savedBook.getPrix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Save multiple books should add all of them")
|
||||||
|
void testSaveMultipleBooks() {
|
||||||
|
repository.save(book1);
|
||||||
|
repository.save(book2);
|
||||||
|
|
||||||
|
List<Book> books = repository.findAll();
|
||||||
|
|
||||||
|
assertEquals(2, books.size());
|
||||||
|
assertTrue(books.contains(book1));
|
||||||
|
assertTrue(books.contains(book2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Find operations")
|
||||||
|
class FindOperations {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpBooks() {
|
||||||
|
repository.save(book1);
|
||||||
|
repository.save(book2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("FindAll should return all books")
|
||||||
|
void testFindAll() {
|
||||||
|
List<Book> books = repository.findAll();
|
||||||
|
|
||||||
|
assertEquals(2, books.size());
|
||||||
|
assertTrue(books.contains(book1));
|
||||||
|
assertTrue(books.contains(book2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("findByIsbn should return book with matching ID")
|
||||||
|
void testFindByIsbn() {
|
||||||
|
Optional<Book> foundBook = repository.findByIsbn(book1.getIsbn());
|
||||||
|
|
||||||
|
assertTrue(foundBook.isPresent());
|
||||||
|
assertEquals(book1.getTitre(), foundBook.get().getTitre());
|
||||||
|
assertEquals(book1.getAuteur(), foundBook.get().getAuteur());
|
||||||
|
assertEquals(book1.getEditeur(), foundBook.get().getEditeur());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("FindByIsbn should return empty Optional when ID doesn't exist")
|
||||||
|
void testFindByIsbnNotFound() {
|
||||||
|
String nonExistentId = "2266346768";
|
||||||
|
|
||||||
|
Optional<Book> foundBook = repository.findByIsbn(nonExistentId);
|
||||||
|
|
||||||
|
assertTrue(foundBook.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("FindByLangue should return book with matching phone number")
|
||||||
|
void testFindByLangue() {
|
||||||
|
Optional<Book> foundBook = repository.findByLangue("fr");
|
||||||
|
|
||||||
|
assertTrue(foundBook.isPresent());
|
||||||
|
assertEquals(book1.getIsbn(), foundBook.get().getIsbn());
|
||||||
|
assertEquals(book1.getTitre(), foundBook.get().getTitre());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("FindByLangue should return empty Optional when phone number doesn't exist")
|
||||||
|
void testFindByLangueNotFound() {
|
||||||
|
Optional<Book> foundBook = repository.findByLangue("0000000000");
|
||||||
|
|
||||||
|
assertTrue(foundBook.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ExistsById should return true when ID exists")
|
||||||
|
void testExistsByIdExists() {
|
||||||
|
boolean exists = repository.existsByIsbn(book1.getIsbn());
|
||||||
|
|
||||||
|
assertTrue(exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ExistsById should return false when ID doesn't exist")
|
||||||
|
void testExistsByIdNotExists() {
|
||||||
|
String nonExistentId = "2266346768";
|
||||||
|
|
||||||
|
boolean exists = repository.existsByIsbn(nonExistentId);
|
||||||
|
|
||||||
|
assertFalse(exists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Delete operations")
|
||||||
|
class DeleteOperations {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpBooks() {
|
||||||
|
repository.save(book1);
|
||||||
|
repository.save(book2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Delete should remove the specified book")
|
||||||
|
void testDelete() {
|
||||||
|
repository.delete(book1);
|
||||||
|
|
||||||
|
List<Book> books = repository.findAll();
|
||||||
|
|
||||||
|
assertEquals(1, books.size());
|
||||||
|
assertFalse(books.contains(book1));
|
||||||
|
assertTrue(books.contains(book2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DeleteAll should remove all books")
|
||||||
|
void testDeleteAll() {
|
||||||
|
repository.deleteAll();
|
||||||
|
|
||||||
|
List<Book> books = repository.findAll();
|
||||||
|
|
||||||
|
assertTrue(books.isEmpty());
|
||||||
|
assertEquals(0, books.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Delete should not throw exception when book doesn't exist")
|
||||||
|
void testDeleteNonExistentBook() {
|
||||||
|
Book nonExistentBook = Book.builder()
|
||||||
|
.isbn("2266346768")
|
||||||
|
.titre("Non")
|
||||||
|
.auteur("l'Existent")
|
||||||
|
.editeur("0000000000")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> repository.delete(nonExistentBook));
|
||||||
|
|
||||||
|
assertEquals(2, repository.findAll().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.usecase;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookDTO;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.BookNotFoundException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.IllegalBookQuantityException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
|
||||||
|
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 org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class BookUseCaseTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private BookRepository bookRepository;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private BookUseCase bookUseCase;
|
||||||
|
|
||||||
|
private String bookIsbn;
|
||||||
|
private Book testBook;
|
||||||
|
private BookInfo validBookInfo;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
bookIsbn = "9782344067949";
|
||||||
|
testBook = Book.builder()
|
||||||
|
.isbn(bookIsbn)
|
||||||
|
.titre("Ruri Dragon")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(100)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
validBookInfo = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo", "Glénat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Register book tests")
|
||||||
|
class RegisterBookTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should register book when valid data is provided")
|
||||||
|
void testRegisterBookWithValidData() throws NotValidBookException {
|
||||||
|
when(bookRepository.save(any(Book.class))).thenReturn(testBook);
|
||||||
|
|
||||||
|
String registeredId = bookUseCase.registerBook(validBookInfo);
|
||||||
|
|
||||||
|
assertNotNull(registeredId);
|
||||||
|
assertEquals(bookIsbn, registeredId);
|
||||||
|
verify(bookRepository, times(1)).save(any(Book.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when book data is not valid")
|
||||||
|
void testRegisterBookWithInvalidData() {
|
||||||
|
BookInfo invalidBookInfo = new BookInfo("", "", "","");
|
||||||
|
|
||||||
|
assertThrows(NotValidBookException.class,
|
||||||
|
() -> bookUseCase.registerBook(invalidBookInfo));
|
||||||
|
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Find book tests")
|
||||||
|
class FindBookTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should return book when phone number exists")
|
||||||
|
void testFindBookByCategorie() {
|
||||||
|
when(bookRepository.findByCategorie("Manga")).thenReturn(Optional.of(testBook));
|
||||||
|
|
||||||
|
Optional<BookDTO> foundBook = bookUseCase.findBookByCategorie("Manga");
|
||||||
|
|
||||||
|
assertTrue(foundBook.isPresent());
|
||||||
|
assertEquals(testBook.getIsbn(), foundBook.get().getIsbn());
|
||||||
|
assertEquals(testBook.getTitre(), foundBook.get().getTitre());
|
||||||
|
verify(bookRepository, times(1)).findByCategorie("Manga");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should return empty Optional when phone number doesn't exist")
|
||||||
|
void testFindBookByCategorieNotFound() {
|
||||||
|
when(bookRepository.findByCategorie("0799999999")).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
Optional<BookDTO> foundBook = bookUseCase.findBookByCategorie("0799999999");
|
||||||
|
|
||||||
|
assertTrue(foundBook.isEmpty());
|
||||||
|
verify(bookRepository, times(1)).findByCategorie("0799999999");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Update book tests")
|
||||||
|
class UpdateBookTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should update book when valid data is provided")
|
||||||
|
void testUpdateBookWithValidData() throws BookNotFoundException, NotValidBookException {
|
||||||
|
when(bookRepository.findByIsbn(bookIsbn)).thenReturn(Optional.of(testBook));
|
||||||
|
|
||||||
|
Book updatedBook = Book.builder()
|
||||||
|
.isbn(bookIsbn)
|
||||||
|
.titre("Ruri Dragon")
|
||||||
|
.auteur("Masaoki Shindo")
|
||||||
|
.editeur("Glénat")
|
||||||
|
.prix(10)
|
||||||
|
.stockInitial(20)
|
||||||
|
.categories(new String[]{"Manga","Shonen"})
|
||||||
|
.langue("fr")
|
||||||
|
.description("Ruri Aoki, lycéenne, se réveille un matin avec des cornes sur la tête ! D’après sa mère, elle tient probablement ça de son père qui est en réalité… un dragon ?! Malgré cette situation inattendue, Ruri se rend au lycée… Bien évidemment, l’apparition de ces cornes attire l’attention de ses camarades, mais ce n’est pas tout : Ruri se découvre d’autres attributs de dragon ! Le quotidien de Ruri s’apprête à connaître bien des bouleversements !")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
when(bookRepository.save(any(Book.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||||
|
|
||||||
|
BookInfo updateInfo = new BookInfo("9782344067949", "Updated", "Masaoki Shindo", "Glénat");
|
||||||
|
|
||||||
|
BookDTO result = bookUseCase.updateBook(bookIsbn, updateInfo);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(bookIsbn, result.getIsbn());
|
||||||
|
assertEquals("Updated", result.getTitre());
|
||||||
|
assertEquals("fr", result.getLangue());
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(bookIsbn);
|
||||||
|
verify(bookRepository, times(1)).save(any(Book.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when book ID doesn't exist")
|
||||||
|
void testUpdateBookNotFound() {
|
||||||
|
String nonExistentId = "2266346768";
|
||||||
|
when(bookRepository.findByIsbn(nonExistentId)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
BookInfo updateInfo = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo", "Glénat");
|
||||||
|
|
||||||
|
assertThrows(BookNotFoundException.class,
|
||||||
|
() -> bookUseCase.updateBook(nonExistentId, updateInfo));
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(nonExistentId);
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when update data is not valid")
|
||||||
|
void testUpdateBookWithInvalidData() {
|
||||||
|
BookInfo invalidUpdateInfo = new BookInfo("", "", "", "");
|
||||||
|
|
||||||
|
assertThrows(NotValidBookException.class,
|
||||||
|
() -> bookUseCase.updateBook(bookIsbn, invalidUpdateInfo));
|
||||||
|
|
||||||
|
verify(bookRepository, never()).findByIsbn(any(String.class));
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Delete book tests")
|
||||||
|
class DeleteBookTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should delete book when ID exists")
|
||||||
|
void testDeleteBook() throws BookNotFoundException {
|
||||||
|
when(bookRepository.findByIsbn(bookIsbn)).thenReturn(Optional.of(testBook));
|
||||||
|
doNothing().when(bookRepository).delete(testBook);
|
||||||
|
|
||||||
|
bookUseCase.deleteBook(bookIsbn);
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(bookIsbn);
|
||||||
|
verify(bookRepository, times(1)).delete(testBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when book ID doesn't exist")
|
||||||
|
void testDeleteBookNotFound() {
|
||||||
|
String nonExistentId = "2266346768";
|
||||||
|
when(bookRepository.findByIsbn(nonExistentId)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThrows(BookNotFoundException.class,
|
||||||
|
() -> bookUseCase.deleteBook(nonExistentId));
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(nonExistentId);
|
||||||
|
verify(bookRepository, never()).delete(any(Book.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Loyalty points tests")
|
||||||
|
class QuantityTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should add loyalty points to book")
|
||||||
|
void testAddQuantity() throws BookNotFoundException {
|
||||||
|
when(bookRepository.findByIsbn(bookIsbn)).thenReturn(Optional.of(testBook));
|
||||||
|
when(bookRepository.save(testBook)).thenReturn(testBook);
|
||||||
|
|
||||||
|
int initialPoints = testBook.getStockInitial();
|
||||||
|
int pointsToAdd = 50;
|
||||||
|
int expectedPoints = initialPoints + pointsToAdd;
|
||||||
|
|
||||||
|
int newPoints = bookUseCase.addQuantity(bookIsbn, pointsToAdd);
|
||||||
|
|
||||||
|
assertEquals(expectedPoints, newPoints);
|
||||||
|
assertEquals(expectedPoints, testBook.getStockInitial());
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(bookIsbn);
|
||||||
|
verify(bookRepository, times(1)).save(testBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when adding points to non-existent book")
|
||||||
|
void testAddQuantityToNonExistentBook() {
|
||||||
|
String nonExistentId = "getStockInitial";
|
||||||
|
when(bookRepository.findByIsbn(nonExistentId)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThrows(BookNotFoundException.class,
|
||||||
|
() -> bookUseCase.addQuantity(nonExistentId, 50));
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(nonExistentId);
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should subtract loyalty points from book")
|
||||||
|
void testSubtractQuantity() throws BookNotFoundException, IllegalBookQuantityException {
|
||||||
|
when(bookRepository.findByIsbn(bookIsbn)).thenReturn(Optional.of(testBook));
|
||||||
|
when(bookRepository.save(testBook)).thenReturn(testBook);
|
||||||
|
|
||||||
|
int initialPoints = testBook.getStockInitial();
|
||||||
|
int pointsToRemove = 30;
|
||||||
|
int expectedPoints = initialPoints - pointsToRemove;
|
||||||
|
|
||||||
|
int newPoints = bookUseCase.subtractQuantity(bookIsbn, pointsToRemove);
|
||||||
|
|
||||||
|
assertEquals(expectedPoints, newPoints);
|
||||||
|
assertEquals(expectedPoints, testBook.getStockInitial());
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(bookIsbn);
|
||||||
|
verify(bookRepository, times(1)).save(testBook);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when trying to remove more points than available")
|
||||||
|
void testSubtractTooManyQuantity() {
|
||||||
|
when(bookRepository.findByIsbn(bookIsbn)).thenReturn(Optional.of(testBook));
|
||||||
|
|
||||||
|
int pointsToRemove = 200;
|
||||||
|
|
||||||
|
assertThrows(IllegalBookQuantityException.class,
|
||||||
|
() -> bookUseCase.subtractQuantity(bookIsbn, pointsToRemove));
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(bookIsbn);
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when subtracting points from non-existent book")
|
||||||
|
void testSubtractQuantityFromNonExistentBook() {
|
||||||
|
String nonExistentId = "subtractQuantity";
|
||||||
|
when(bookRepository.findByIsbn(nonExistentId)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThrows(BookNotFoundException.class,
|
||||||
|
() -> bookUseCase.subtractQuantity(nonExistentId, 50));
|
||||||
|
|
||||||
|
verify(bookRepository, times(1)).findByIsbn(nonExistentId);
|
||||||
|
verify(bookRepository, never()).save(any(Book.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
package fr.iut_fbleau.but3.dev62.mylibrary.book.validator;
|
||||||
|
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.BookInfo;
|
||||||
|
import fr.iut_fbleau.but3.dev62.mylibrary.book.exception.NotValidBookException;
|
||||||
|
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 static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BookValidatorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should validate book with valid data")
|
||||||
|
void testValidateValidBook() {
|
||||||
|
BookInfo validBook = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo","Glénat");
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> BookValidator.validate(validBook));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("ISBN validation tests")
|
||||||
|
class ISBNValidationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when ISBN is blank")
|
||||||
|
void testValidateBlankISBN() {
|
||||||
|
BookInfo bookWithBlankISBN = new BookInfo("", "Ruri Dragon", "Masaoki Shindo","Glénat");
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithBlankISBN)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.ISBN_IS_NOT_VALID, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when ISBN is more than 13 long")
|
||||||
|
void testNotValidateTooLongISBN() {
|
||||||
|
BookInfo bookWithBlankISBN = new BookInfo("978234406794976433568", "Ruri Dragon", "Masaoki Shindo","Glénat");
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithBlankISBN)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.ISBN_IS_NOT_VALID, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {" ", " ", "\t", "\n"})
|
||||||
|
@DisplayName("Should throw exception when first name contains only whitespace")
|
||||||
|
void testValidateWhitespaceISBN(String whitespace) {
|
||||||
|
BookInfo bookWithWhitespaceISBN = new BookInfo(whitespace, "Ruri Dragon", "Masaoki Shindo","Glénat");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithWhitespaceISBN)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.ISBN_IS_NOT_VALID, exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Titre validation tests")
|
||||||
|
class TitreValidationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when last name is blank")
|
||||||
|
void testValidateBlankTitre() {
|
||||||
|
BookInfo bookWithBlankTitre = new BookInfo("9782344067949", "", "Masaoki Shindo","Glénat");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithBlankTitre)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.TITRE_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {" ", " ", "\t", "\n"})
|
||||||
|
@DisplayName("Should throw exception when last name contains only whitespace")
|
||||||
|
void testValidateWhitespaceTitre(String whitespace) {
|
||||||
|
BookInfo bookWithWhitespaceTitre = new BookInfo("9782344067949", whitespace, "Masaoki Shindo","Glénat");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithWhitespaceTitre)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.TITRE_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Auteur validation tests")
|
||||||
|
class AuteurValidationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when last name is blank")
|
||||||
|
void testValidateBlankAuteur() {
|
||||||
|
BookInfo bookWithBlankAuteur = new BookInfo("9782344067949", "Ruri Dragon", "","Glénat");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithBlankAuteur)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.AUTEUR_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {" ", " ", "\t", "\n"})
|
||||||
|
@DisplayName("Should throw exception when last name contains only whitespace")
|
||||||
|
void testValidateWhitespaceAuteur(String whitespace) {
|
||||||
|
BookInfo bookWithWhitespaceAuteur = new BookInfo("9782344067949", "Ruri Dragon", whitespace,"Glénat");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithWhitespaceAuteur)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.AUTEUR_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Editeur validation tests")
|
||||||
|
class EditeurValidationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should throw exception when phone number is blank")
|
||||||
|
void testValidateBlankEditeur() {
|
||||||
|
BookInfo bookWithBlankEditeur = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo","");
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithBlankEditeur)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.EDITEUR_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {" ", " ", "\t", "\n"})
|
||||||
|
@DisplayName("Should throw exception when phone number contains only whitespace")
|
||||||
|
void testValidateWhitespaceEditeur(String whitespace) {
|
||||||
|
BookInfo bookWithWhitespaceEditeur = new BookInfo("9782344067949", "Ruri Dragon", "Masaoki Shindo",whitespace);
|
||||||
|
|
||||||
|
NotValidBookException exception = assertThrows(
|
||||||
|
NotValidBookException.class,
|
||||||
|
() -> BookValidator.validate(bookWithWhitespaceEditeur)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(BookValidator.EDITEUR_CANNOT_BE_BLANK, exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user